summaryrefslogtreecommitdiff
path: root/src/ulib/stdio.c
diff options
context:
space:
mode:
authorRichard Qin <richard.qin.x@gmail.com>2026-07-10 11:31:46 +0800
committerRichard Qin <richard.qin.x@gmail.com>2026-07-10 11:31:46 +0800
commite90b72ec3082588b296956730bd2930cf8d5d671 (patch)
tree36ff6916af9b4176ea5a9662219d11e721f0b691 /src/ulib/stdio.c
parent1767d390fbf3d0c65389de46caf0b6d43ef3b6ad (diff)
downloadlume-e90b72ec3082588b296956730bd2930cf8d5d671.tar.gz
lume-e90b72ec3082588b296956730bd2930cf8d5d671.tar.xz
refactor: promote new architecture to repository root
Archive the deprecated implementation under lume-legacy, make the new kernel the default root-level build, and update repository entry points without changing kernel behavior.
Diffstat (limited to 'src/ulib/stdio.c')
-rw-r--r--src/ulib/stdio.c1056
1 files changed, 0 insertions, 1056 deletions
diff --git a/src/ulib/stdio.c b/src/ulib/stdio.c
deleted file mode 100644
index e81f69a..0000000
--- a/src/ulib/stdio.c
+++ /dev/null
@@ -1,1056 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * Copyright (C) 2026 Richard QIn
- */
-#include "ulib/stdio.h"
-#include "ulib/string.h"
-#include "ulib/stdlib.h"
-
-/* Include STB Sprintf Implementation */
-#define STB_SPRINTF_IMPLEMENTATION
-#include "ulib/stb_sprintf.h"
-
-const int STDIN_FD = 0;
-const int STDOUT_FD = 1;
-const int STDERR_FD = 2;
-
-
-
-extern int open(const char *path, int flags);
-extern int close(int fd);
-extern int read(int fd, void *buf, uint64 count);
-extern int write(int fd, const void *buf, uint64 count);
-extern int lseek(int fd, int offset, int whence);
-
-static int isspace(int c)
-{
- return c == ' ' || c == '\t' || c == '\n' || c == '\v' || c == '\f' || c == '\r';
-}
-
-/* Core Formatting Implementation */
-
-static int _ul_to_str_invert(char *buf, uint64 val, int base, int uppercase)
-{
- int i = 0;
- const char *digits = uppercase ? "0123456789ABCDEF" : "0123456789abcdef";
- if (val == 0)
- {
- buf[i++] = '0';
- return i;
- }
- while (val != 0)
- {
- buf[i++] = digits[val % base];
- val /= base;
- }
- return i;
-}
-
-typedef struct
-{
- char *buf;
- uint64 limit;
- uint64 written;
- FILE *stream;
-} _OutContext;
-
-static void _out_char(_OutContext *ctx, char c)
-{
- if (ctx->stream)
- {
- fputc(c, ctx->stream);
- ctx->written++;
- }
- else
- {
- if (ctx->limit > 0 && ctx->written < ctx->limit - 1)
- {
- ctx->buf[ctx->written] = c;
- }
- ctx->written++;
- }
-}
-
-static int _vprintf_core(_OutContext *ctx, const char *format, va_list ap)
-{
- const char *p = format;
- char num_buf[32];
-
- while (*p)
- {
- if (*p != '%')
- {
- _out_char(ctx, *p++);
- continue;
- }
- p++;
-
- int flag_left = 0, flag_zero = 0, flag_plus = 0, flag_space = 0, flag_hash = 0;
- while (1)
- {
- if (*p == '-')
- flag_left = 1;
- else if (*p == '0')
- flag_zero = 1;
- else if (*p == '+')
- flag_plus = 1;
- else if (*p == ' ')
- flag_space = 1;
- else if (*p == '#')
- flag_hash = 1;
- else
- break;
- p++;
- }
-
- int width = 0;
- if (*p == '*')
- {
- width = va_arg(ap, int);
- if (width < 0)
- {
- flag_left = 1;
- width = -width;
- }
- p++;
- }
- else
- {
- while (*p >= '0' && *p <= '9')
- {
- width = width * 10 + (*p - '0');
- p++;
- }
- }
-
- int precision = -1;
- if (*p == '.')
- {
- p++;
- if (*p == '*')
- {
- precision = va_arg(ap, int);
- p++;
- }
- else
- {
- precision = 0;
- while (*p >= '0' && *p <= '9')
- {
- precision = precision * 10 + (*p - '0');
- p++;
- }
- }
- }
-
- int len_mod = 0;
- if (*p == 'l')
- {
- len_mod = 1;
- p++;
- if (*p == 'l')
- {
- len_mod = 2;
- p++;
- }
- }
- else if (*p == 'z')
- {
- len_mod = 2;
- p++;
- }
-
- char spec = *p++;
- if (!spec)
- break;
-
- if (spec == 'd' || spec == 'i' || spec == 'u' || spec == 'x' || spec == 'X' || spec == 'p')
- {
- uint64 val;
- int is_signed = (spec == 'd' || spec == 'i');
- int base = (spec == 'x' || spec == 'X' || spec == 'p') ? 16 : 10;
-
- if (spec == 'p')
- val = (uint64)va_arg(ap, void *);
- else if (len_mod == 2)
- val = is_signed ? (uint64)va_arg(ap, int64) : va_arg(ap, uint64);
- else if (len_mod == 1)
- val = is_signed ? (uint64)va_arg(ap, long) : (uint64)va_arg(ap, unsigned long);
- else
- val = is_signed ? (uint64)((int64)va_arg(ap, int)) : (uint64)va_arg(ap, uint32);
-
- char sign_char = 0;
- if (is_signed)
- {
- int64 sval = (int64)val;
- if (sval < 0)
- {
- sign_char = '-';
- val = (uint64)(-sval);
- }
- else if (flag_plus)
- sign_char = '+';
- else if (flag_space)
- sign_char = ' ';
- }
-
- int digit_len = _ul_to_str_invert(num_buf, val, base, (spec == 'X'));
- if (precision >= 0)
- flag_zero = 0;
- int prec_zeros = (precision > digit_len) ? precision - digit_len : 0;
- if (precision == 0 && val == 0)
- digit_len = 0;
-
- int prefix_len = sign_char ? 1 : 0;
- char *prefix_str = NULL;
- if (spec == 'p' || (flag_hash && val != 0 && (spec == 'x' || spec == 'X')))
- {
- prefix_str = (spec == 'X') ? "0X" : "0x";
- prefix_len += 2;
- }
-
- int padding = (width > prefix_len + prec_zeros + digit_len) ? width - (prefix_len + prec_zeros + digit_len) : 0;
-
- if (!flag_left && !flag_zero)
- for (int i = 0; i < padding; i++)
- _out_char(ctx, ' ');
- if (sign_char)
- _out_char(ctx, sign_char);
- if (prefix_str)
- {
- _out_char(ctx, prefix_str[0]);
- _out_char(ctx, prefix_str[1]);
- }
- int total_zeros = prec_zeros + ((flag_zero && !flag_left) ? padding : 0);
- for (int i = 0; i < total_zeros; i++)
- _out_char(ctx, '0');
- for (int i = digit_len - 1; i >= 0; i--)
- _out_char(ctx, num_buf[i]);
- if (flag_left)
- for (int i = 0; i < padding; i++)
- _out_char(ctx, ' ');
- }
- else if (spec == 'f' || spec == 'F' || spec == 'e' || spec == 'E' || spec == 'g' || spec == 'G')
- {
- char fmt_tmp[32];
- int f_idx = 0;
- fmt_tmp[f_idx++] = '%';
- if (flag_left)
- fmt_tmp[f_idx++] = '-';
- if (flag_zero)
- fmt_tmp[f_idx++] = '0';
- if (flag_plus)
- fmt_tmp[f_idx++] = '+';
- if (flag_space)
- fmt_tmp[f_idx++] = ' ';
- if (flag_hash)
- fmt_tmp[f_idx++] = '#';
- if (width > 0)
- f_idx += sprintf(&fmt_tmp[f_idx], "%d", width);
- if (precision >= 0)
- f_idx += sprintf(&fmt_tmp[f_idx], ".%d", precision);
- fmt_tmp[f_idx++] = spec;
- fmt_tmp[f_idx] = '\0';
- double f_val = va_arg(ap, double);
- char f_buf[128];
- stbsp_snprintf(f_buf, sizeof(f_buf), fmt_tmp, f_val);
- for (int i = 0; f_buf[i] != '\0'; i++)
- _out_char(ctx, f_buf[i]);
- }
- else if (spec == 's')
- {
- const char *s = va_arg(ap, char *);
- if (!s)
- s = "(null)";
- int len = 0;
- const char *tmp = s;
- while (*tmp && (precision < 0 || len < precision))
- {
- tmp++;
- len++;
- }
- int padding = (width > len) ? width - len : 0;
- if (!flag_left)
- for (int i = 0; i < padding; i++)
- _out_char(ctx, ' ');
- for (int i = 0; i < len; i++)
- _out_char(ctx, s[i]);
- if (flag_left)
- for (int i = 0; i < padding; i++)
- _out_char(ctx, ' ');
- }
- else if (spec == 'c')
- {
- char c = (char)va_arg(ap, int);
- int padding = (width > 1) ? width - 1 : 0;
- if (!flag_left)
- for (int i = 0; i < padding; i++)
- _out_char(ctx, ' ');
- _out_char(ctx, c);
- if (flag_left)
- for (int i = 0; i < padding; i++)
- _out_char(ctx, ' ');
- }
- else
- {
- _out_char(ctx, '%');
- if (spec != '%')
- _out_char(ctx, spec);
- }
- }
- return (int)ctx->written;
-}
-
-int vsnprintf(char *str, uint64 size, const char *format, va_list ap)
-{
- _OutContext ctx;
- ctx.buf = str;
- ctx.limit = size;
- ctx.written = 0;
- ctx.stream = NULL;
- _vprintf_core(&ctx, format, ap);
- if (size > 0)
- {
- if (ctx.written < size)
- str[ctx.written] = '\0';
- else
- str[size - 1] = '\0';
- }
- return (int)ctx.written;
-}
-int snprintf(char *str, uint64 size, const char *format, ...)
-{
- va_list ap;
- va_start(ap, format);
- int ret = vsnprintf(str, size, format, ap);
- va_end(ap);
- return ret;
-}
-int sprintf(char *str, const char *format, ...)
-{
- va_list ap;
- va_start(ap, format);
- int ret = vsnprintf(str, (uint64)-1, format, ap);
- va_end(ap);
- return ret;
-}
-int printf(const char *format, ...)
-{
- va_list ap;
- va_start(ap, format);
- _OutContext ctx;
- ctx.buf = NULL;
- ctx.limit = 0;
- ctx.written = 0;
- ctx.stream = stdout;
- _vprintf_core(&ctx, format, ap);
- va_end(ap);
- return (int)ctx.written;
-}
-
-/* Core Function Implementation */
-
-typedef struct
-{
- const char *buf;
- int fd;
- uint64 pos;
- int ungotten;
-} _InContext;
-
-static int _in_char(_InContext *ctx)
-{
- if (ctx->ungotten >= 0)
- {
- int c = ctx->ungotten;
- ctx->ungotten = -1;
- return c;
- }
- if (ctx->fd == -1)
- {
- if (ctx->buf[ctx->pos] == '\0')
- return -1;
- return (unsigned char)ctx->buf[ctx->pos++];
- }
- char c;
- if (read(ctx->fd, &c, 1) == 1)
- return (unsigned char)c;
- return -1;
-}
-
-static void _unget_char(_InContext *ctx, int c)
-{
- if (c != -1)
- ctx->ungotten = c;
-}
-static void _skip_space(_InContext *ctx)
-{
- int c;
- while ((c = _in_char(ctx)) != -1)
- {
- if (!isspace(c))
- {
- _unget_char(ctx, c);
- break;
- }
- }
-}
-
-static double _simple_strtod(const char *str, char **endptr)
-{
- double val = 0.0;
- int sign = 1;
- if (*str == '-')
- {
- sign = -1;
- str++;
- }
- else if (*str == '+')
- str++;
- while (*str >= '0' && *str <= '9')
- {
- val = val * 10.0 + (*str - '0');
- str++;
- }
- if (*str == '.')
- {
- str++;
- double div = 10.0;
- while (*str >= '0' && *str <= '9')
- {
- val += (*str - '0') / div;
- div *= 10.0;
- str++;
- }
- }
- if (*str == 'e' || *str == 'E')
- {
- str++;
- int esign = 1;
- if (*str == '-')
- {
- esign = -1;
- str++;
- }
- else if (*str == '+')
- str++;
- int eval = 0;
- while (*str >= '0' && *str <= '9')
- {
- eval = eval * 10 + (*str - '0');
- str++;
- }
- double p = 1.0;
- while (eval--)
- p *= 10.0;
- if (esign == 1)
- val *= p;
- else
- val /= p;
- }
- if (endptr)
- *endptr = (char *)str;
- return sign * val;
-}
-
-static int _vscanf_core(_InContext *ctx, const char *format, va_list ap)
-{
- int assigned = 0;
- const char *p = format;
- while (*p)
- {
- if (isspace(*p))
- {
- _skip_space(ctx);
- while (isspace(*p))
- p++;
- continue;
- }
- if (*p != '%')
- {
- _skip_space(ctx);
- int c = _in_char(ctx);
- if (c != *p)
- {
- _unget_char(ctx, c);
- return assigned;
- }
- p++;
- continue;
- }
- p++;
- int suppress = 0;
- if (*p == '*')
- {
- suppress = 1;
- p++;
- }
- int width = -1;
- while (*p >= '0' && *p <= '9')
- {
- if (width == -1)
- width = 0;
- width = width * 10 + (*p - '0');
- p++;
- }
- int len_mod = 0;
- if (*p == 'l')
- {
- len_mod = 1;
- p++;
- if (*p == 'l')
- {
- len_mod = 2;
- p++;
- }
- }
- else if (*p == 'h')
- {
- p++;
- if (*p == 'h')
- p++;
- }
- char spec = *p++;
- if (!spec)
- break;
-
- if (spec == 'd' || spec == 'i' || spec == 'u' || spec == 'x')
- {
- _skip_space(ctx);
- char num_buf[64];
- int i = 0, c = _in_char(ctx);
- if (c == '-' || c == '+')
- {
- num_buf[i++] = (char)c;
- c = _in_char(ctx);
- }
- int base = (spec == 'x') ? 16 : (spec == 'i' ? 0 : 10);
- while (c != -1 && i < 63)
- {
- int digit = (c >= '0' && c <= '9');
- int hex = (base == 16 || base == 0) && ((c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'));
- int x = (c == 'x' || c == 'X');
- if (base == 0 && i == 1 && num_buf[0] == '0' && x)
- base = 16;
- if (width > 0 && i >= width)
- break;
- if (digit || hex || x)
- {
- num_buf[i++] = (char)c;
- c = _in_char(ctx);
- }
- else
- break;
- }
- num_buf[i] = '\0';
- _unget_char(ctx, c);
- if (i == 0)
- return assigned;
- if (!suppress)
- {
- int64 val = strtoll(num_buf, NULL, base);
- if (len_mod == 2)
- *va_arg(ap, int64 *) = val;
- else if (len_mod == 1)
- *va_arg(ap, long *) = (long)val;
- else
- *va_arg(ap, int *) = (int)val;
- assigned++;
- }
- }
- else if (spec == 'f' || spec == 'F' || spec == 'e' || spec == 'E' || spec == 'g' || spec == 'G')
- {
- _skip_space(ctx);
- char num_buf[64];
- int i = 0, c = _in_char(ctx);
- if (c == '-' || c == '+')
- {
- num_buf[i++] = (char)c;
- c = _in_char(ctx);
- }
- while (c != -1 && i < 63)
- {
- if ((c >= '0' && c <= '9') || c == '.' || c == 'e' || c == 'E' || c == '+' || c == '-')
- {
- num_buf[i++] = (char)c;
- c = _in_char(ctx);
- }
- else
- break;
- }
- num_buf[i] = '\0';
- _unget_char(ctx, c);
- if (i == 0)
- return assigned;
- if (!suppress)
- {
- double val = _simple_strtod(num_buf, NULL);
- if (len_mod == 1)
- *va_arg(ap, double *) = val;
- else
- *va_arg(ap, float *) = (float)val;
- assigned++;
- }
- }
- else if (spec == 's')
- {
- _skip_space(ctx);
- char *buf = suppress ? NULL : va_arg(ap, char *);
- int i = 0, c = _in_char(ctx);
- while (c != -1 && !isspace(c))
- {
- if (width > 0 && i >= width)
- break;
- if (!suppress)
- buf[i] = (char)c;
- i++;
- c = _in_char(ctx);
- }
- if (!suppress)
- buf[i] = '\0';
- _unget_char(ctx, c);
- if (i > 0 && !suppress)
- assigned++;
- }
- else if (spec == 'c')
- {
- int count = (width > 0) ? width : 1;
- char *buf = suppress ? NULL : va_arg(ap, char *);
- for (int i = 0; i < count; i++)
- {
- int c = _in_char(ctx);
- if (c == -1)
- return assigned;
- if (!suppress)
- buf[i] = (char)c;
- }
- if (!suppress)
- assigned++;
- }
- }
- return assigned;
-}
-
-int sscanf(const char *str, const char *format, ...)
-{
- va_list ap;
- va_start(ap, format);
- _InContext ctx;
- ctx.buf = str;
- ctx.fd = -1;
- ctx.pos = 0;
- ctx.ungotten = -1;
- int ret = _vscanf_core(&ctx, format, ap);
- va_end(ap);
- return ret;
-}
-int scanf(const char *format, ...)
-{
- va_list ap;
- va_start(ap, format);
- _InContext ctx;
- ctx.buf = NULL;
- ctx.fd = STDIN_FD;
- ctx.pos = 0;
- ctx.ungotten = -1;
- int ret = _vscanf_core(&ctx, format, ap);
- va_end(ap);
- return ret;
-}
-
-/* FILE Stream Implementation */
-
-#define O_RDONLY 00
-#define O_WRONLY 01
-#define O_RDWR 02
-#define O_CREAT 0100
-#define O_TRUNC 01000
-#define O_APPEND 02000
-
-
-static FILE _stdin = {.fd = 0, .buf_mode = 1};
-static FILE _stdout = {.fd = 1, .buf_mode = 1};
-static FILE _stderr = {.fd = 2, .buf_mode = 2};
-
-FILE *stdin = &_stdin;
-FILE *stdout = &_stdout;
-FILE *stderr = &_stderr;
-
-FILE *fopen(const char *filename, const char *mode)
-{
- 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
- return NULL;
-
- int64 fd = open(filename, flags);
- if (fd < 0)
- return NULL;
-
- FILE *f = (FILE *)malloc(sizeof(FILE));
- if (!f)
- {
- close(fd);
- return NULL;
- }
-
- memset(f, 0, sizeof(FILE));
- f->fd = (int)fd;
- f->flags = flags;
-
- if (fd == 1)
- f->buf_mode = 1;
- else if (fd == 2)
- f->buf_mode = 2;
- else
- f->buf_mode = 0;
- return f;
-}
-
-int fclose(FILE *stream)
-{
- if (!stream)
- return -1;
- fflush(stream);
- if (stream != stdin && stream != stdout && stream != stderr)
- {
- close(stream->fd);
- free(stream);
- }
- return 0;
-}
-
-int fflush(FILE *stream)
-{
- if (!stream)
- return EOF;
-
- if (stream->buf_write_pos > 0)
- {
- int64 ret = write(stream->fd, stream->buffer, stream->buf_write_pos);
- if (ret < stream->buf_write_pos)
- {
- stream->error = 1;
- stream->buf_write_pos = 0;
- return EOF;
- }
- stream->buf_write_pos = 0;
- }
- return 0;
-}
-
-int fprintf(FILE *stream, const char *format, ...)
-{
- if (!stream)
- return -1;
- va_list ap;
- va_start(ap, format);
- _OutContext ctx;
- ctx.buf = NULL;
- ctx.limit = 0;
- ctx.written = 0;
- ctx.stream = stream;
- _vprintf_core(&ctx, format, ap);
- va_end(ap);
- return (int)ctx.written;
-}
-
-int fscanf(FILE *stream, const char *format, ...)
-{
- if (!stream)
- return -1;
- va_list ap;
- va_start(ap, format);
- _InContext ctx;
- ctx.buf = NULL;
- ctx.fd = stream->fd;
- ctx.pos = 0;
- ctx.ungotten = -1;
- int ret = _vscanf_core(&ctx, format, ap);
- va_end(ap);
- return ret;
-}
-
-int fputc(int c, FILE *stream)
-{
- if (!stream)
- return EOF;
- if (stream->buf_mode == 2)
- {
- char ch = (char)c;
- if (write(stream->fd, &ch, 1) != 1)
- {
- stream->error = 1;
- return EOF;
- }
- return c;
- }
-
- stream->buffer[stream->buf_write_pos++] = (char)c;
-
- if (stream->buf_write_pos >= BUFSIZ)
- {
- fflush(stream);
- }
- else if (stream->buf_mode == 1 && c == '\n')
- {
- fflush(stream);
- }
-
- return c;
-}
-
-int fputs(const char *s, FILE *stream)
-{
- if (!stream)
- return -1;
- while (*s)
- {
- if (fputc(*s++, stream) == EOF)
- return EOF;
- }
- return 0;
-}
-
-int fgetc(FILE *stream)
-{
- if (!stream)
- return EOF;
-
- if (stream->buf_write_pos > 0)
- {
- fflush(stream);
- }
-
- if (stream->buf_read_pos < stream->buf_read_cnt)
- {
- return (unsigned char)stream->buffer[stream->buf_read_pos++];
- }
-
- int64 ret = read(stream->fd, stream->buffer, BUFSIZ);
- if (ret <= 0)
- {
- if (ret == 0)
- stream->eof = 1;
- else
- stream->error = 1;
- return EOF;
- }
-
- stream->buf_read_cnt = (int)ret;
- stream->buf_read_pos = 0;
- return (unsigned char)stream->buffer[stream->buf_read_pos++];
-}
-
-char *fgets(char *str, int n, FILE *stream)
-{
- if (!stream || n <= 0)
- return NULL;
- int i = 0, c;
- while (i < n - 1)
- {
- c = fgetc(stream);
- if (c == -1)
- {
- if (i == 0)
- return NULL;
- break;
- }
- str[i++] = (char)c;
- if (c == '\n')
- break;
- }
- str[i] = '\0';
- return str;
-}
-
-uint64 fread(void *ptr, uint64 size, uint64 nmemb, FILE *stream)
-{
- if (!stream || size == 0 || nmemb == 0)
- return 0;
-
- uint64 total_bytes = size * nmemb;
- uint64 bytes_read = 0;
- char *dst = (char *)ptr;
-
- if (stream->buf_write_pos > 0)
- fflush(stream);
-
- while (bytes_read < total_bytes)
- {
- if (stream->buf_read_pos < stream->buf_read_cnt)
- {
- uint64 available = stream->buf_read_cnt - stream->buf_read_pos;
- uint64 remaining = total_bytes - bytes_read;
- uint64 to_copy = (available < remaining) ? available : remaining;
-
- memcpy(dst + bytes_read, stream->buffer + stream->buf_read_pos, to_copy);
-
- stream->buf_read_pos += to_copy;
- bytes_read += to_copy;
- }
- else
- {
- uint64 remaining = total_bytes - bytes_read;
-
- if (remaining >= BUFSIZ)
- {
- int64 ret = read(stream->fd, dst + bytes_read, remaining);
- if (ret <= 0)
- {
- if (ret == 0)
- stream->eof = 1;
- else
- stream->error = 1;
- return bytes_read / size;
- }
- bytes_read += ret;
- }
- else
- {
- stream->buf_read_pos = 0;
- stream->buf_read_cnt = 0;
- int64 ret = read(stream->fd, stream->buffer, BUFSIZ);
-
- if (ret <= 0)
- {
- if (ret == 0)
- stream->eof = 1;
- else
- stream->error = 1;
- return bytes_read / size;
- }
- stream->buf_read_cnt = (int)ret;
- }
- }
- }
- return bytes_read / size;
-}
-
-uint64 fwrite(const void *ptr, uint64 size, uint64 nmemb, FILE *stream)
-{
- if (!stream || !ptr || size == 0 || nmemb == 0)
- return 0;
- uint64 total_bytes = size * nmemb;
- const char *src = (const char *)ptr;
- uint64 bytes_written = 0;
-
- if (stream->buf_mode == 2)
- {
- while (bytes_written < total_bytes)
- {
- int64 ret = write(stream->fd, src + bytes_written, total_bytes - bytes_written);
- if (ret <= 0)
- {
- stream->error = 1;
- break;
- }
- bytes_written += ret;
- }
- return bytes_written / size;
- }
-
- while (bytes_written < total_bytes)
- {
- uint64 space_left = BUFSIZ - stream->buf_write_pos;
- uint64 remaining = total_bytes - bytes_written;
-
- if (remaining <= space_left)
- {
- memcpy(stream->buffer + stream->buf_write_pos, src + bytes_written, remaining);
- stream->buf_write_pos += remaining;
- bytes_written += remaining;
- if (stream->buf_write_pos == BUFSIZ)
- fflush(stream);
- }
- else
- {
- memcpy(stream->buffer + stream->buf_write_pos, src + bytes_written, space_left);
- stream->buf_write_pos += space_left;
- bytes_written += space_left;
- fflush(stream);
- }
- }
-
- return bytes_written / size;
-}
-
-int fseek(FILE *stream, long offset, int whence)
-{
- if (!stream)
- return -1;
-
- if (stream->buf_write_pos > 0)
- {
- fflush(stream);
- }
- stream->buf_read_pos = 0;
- stream->buf_read_cnt = 0;
- stream->eof = 0;
-
- if (lseek(stream->fd, offset, whence) < 0)
- {
- stream->error = 1;
- return -1;
- }
- return 0;
-}
-long ftell(FILE *stream)
-{
- if (!stream)
- return -1L;
- int64 ret = lseek(stream->fd, 0, SEEK_CUR);
- if (ret < 0)
- {
- stream->error = 1;
- return -1L;
- }
- return (long)ret;
-}
-void rewind(FILE *stream)
-{
- if (stream)
- {
- fseek(stream, 0, SEEK_SET);
- stream->error = 0;
- }
-}
-
-int feof(FILE *stream)
-{
- return (stream) ? stream->eof : 1;
-}
-int ferror(FILE *stream)
-{
- return (stream) ? stream->error : 1;
-}
-void clearerr(FILE *stream)
-{
- if (stream)
- {
- stream->error = 0;
- stream->eof = 0;
- }
-}
-
-int ungetc(int c, FILE *stream)
-{
- if (!stream || c == EOF)
- return EOF;
-
- if (stream->buf_read_pos > 0)
- {
- stream->buf_read_pos--;
- stream->buffer[stream->buf_read_pos] = (char)c;
- stream->eof = 0;
- return c;
- }
- return EOF;
-} \ No newline at end of file