summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakob Kaivo <jkk@ung.org>2024-06-06 17:44:42 -0400
committerJakob Kaivo <jkk@ung.org>2024-06-06 17:44:42 -0400
commit5195e91c57e8209bc0b54b470213497def444ea7 (patch)
tree000ac605742e81d99947196de2719e22876e3f8c
parentd8353afab7c754968ebbaa8fa1cd3f6f4b83d86e (diff)
more efficient output, especially padding
-rw-r--r--src/stdio/__printf.c72
1 files changed, 41 insertions, 31 deletions
diff --git a/src/stdio/__printf.c b/src/stdio/__printf.c
index 34904d30..15b172f2 100644
--- a/src/stdio/__printf.c
+++ b/src/stdio/__printf.c
@@ -1,8 +1,6 @@
-#include <ctype.h>
#include <limits.h>
#include <stdio.h>
#include <stddef.h>
-#include <stdlib.h>
#include <string.h>
#include <wchar.h>
@@ -18,78 +16,90 @@
#define NUMBUFLEN 64
-static int __output(struct io_options *opt, struct io_conversion *conv, const char *str, size_t len)
+static void __output(struct io_options *opt, struct io_conversion *conv, const char *str, size_t len)
{
+ static char pad[BUFSIZ] = "";
size_t olen = strlen(str);
if (len == 0) {
len = olen;
}
- if (conv && olen < conv->width && (conv->flags & F_WIDTH) && !(conv->flags & F_LEFT)) {
- for (size_t i = 0; i < conv->width - olen; i++) {
- __output(opt, NULL, " ", 1);
- }
+ if (pad[0] == '\0') {
+ memset(pad, ' ', sizeof(pad));
}
-
- for (size_t i = 0; i < len && str[i] != '\0'; i++) {
- if (opt->ret == INT_MAX) {
- UNDEFINED("In call to %s(): Attempting to output more than INT_MAX characters", opt->fnname);
- }
- if (opt->stream) {
- fputc(str[i], opt->stream);
- } else if (opt->string) {
- if ((size_t)opt->ret < opt->maxlen) {
- opt->string[opt->ret] = str[i];
- }
+
+ if (conv && (conv->flags & F_WIDTH)) {
+ if (conv->width < olen) {
+ conv->width = 0;
} else {
- /* file descriptor */
+ conv->width -= olen;
}
- opt->ret++;
}
- if (conv && olen < conv->width && (conv->flags & F_WIDTH) && (conv->flags & F_LEFT)) {
- for (size_t i = 0; i < conv->width - olen; i++) {
- __output(opt, NULL, " ", 1);
+ if (conv && (conv->flags & F_WIDTH) && !(conv->flags & F_LEFT)) {
+ while (conv->width > 0) {
+ __output(opt, NULL, pad, conv->width % BUFSIZ);
+ conv->width -= conv->width % BUFSIZ;
}
}
- return 0;
+ if (len > INT_MAX || opt->ret > INT_MAX - (int)len) {
+ UNDEFINED("In call to %s(): Attempting to output more than INT_MAX characters", opt->fnname);
+ }
+
+ /* TODO: check for errors */
+ if (opt->stream) {
+ opt->ret += fwrite(str, 1, len, opt->stream);
+ } else if (opt->string) {
+ memcpy(opt->string + opt->ret, str, len);
+ opt->ret += len;
+ } else {
+ /* opt->ret += write(opt->fd, str, len); */
+ }
+
+ if (conv && (conv->flags & F_WIDTH) && (conv->flags & F_LEFT)) {
+ while (conv->width > 0) {
+ __output(opt, NULL, pad, conv->width % BUFSIZ);
+ conv->width -= conv->width % BUFSIZ;
+ }
+ }
}
static void __utos(char *s, uintmax_t n, enum conversion_flags flags, int precision, int base)
{
- char digits[] = "0123456789abcdef";
+ char lower[] = "0123456789abcdef";
+ char upper[] = "0123456789ABCDEF";
+ char *digits = (flags & F_UPPER ? upper : lower);
char sign = '+';
char buf[NUMBUFLEN + 1];
char *out = buf + NUMBUFLEN;
- if (flags & F_UPPER && base > 10) {
- size_t i;
- for (i = 0; i < sizeof(digits); i++) {
- digits[i] = (char)toupper(digits[i]);
- }
- }
+
*out = '\0';
out--;
if (n == 0) {
*out = '0';
out--;
}
+
while (n > 0) {
precision--;
*out = digits[n % base];
n /= base;
out--;
}
+
/* TODO: this has a risk of overflowing */
while (precision > 0 && (flags & (F_ZERO | F_PRECISION))) {
*out = '0';
precision--;
out--;
}
+
if (flags & F_SIGN) {
*out = sign;
out--;
}
+
out++;
while ((*s++ = *out++) != 0) {
continue;