static const char flag_chars[] = "#0- +";
-#define FLAG_ALT (1<<0)
-#define FLAG_ZERO (1<<1)
-#define FLAG_LEFTJUSTIFY (1<<2)
-#define FLAG_SPACEPOSITIVE (1<<3)
-#define FLAG_PLUSPOSITIVE (1<<4)
-#define FLAG_NUMERIC (1<<5)
-#define FLAG_SIGNED (1<<6)
-#define FLAG_NEGATIVE (1<<7)
-#define FLAG_ALT2 (1<<8)
-#define FLAG_CAPS (1<<9)
-
-
-// FIXME: use something like IO_FILE to abstract this into a more flexible, stream based, vprintf
-void
+#define FLAG_ALT (1 << 0)
+#define FLAG_ZERO (1 << 1)
+#define FLAG_LEFTJUSTIFY (1 << 2)
+#define FLAG_SPACEPOSITIVE (1 << 3)
+#define FLAG_PLUSPOSITIVE (1 << 4)
+#define FLAG_NUMERIC (1 << 5)
+#define FLAG_SIGNED (1 << 6)
+#define FLAG_NEGATIVE (1 << 7)
+#define FLAG_ALT2 (1 << 8)
+#define FLAG_CAPS (1 << 9)
+
+// FIXME: use something like IO_FILE to abstract this into a more flexible,
+// stream based, vprintf
+size_t
__sprintf_internal(char* buffer, char* fmt, size_t max_len, va_list vargs)
{
// This sprintf just a random implementation I found it on Internet . lol.
// Of course, with some modifications for porting to LunaixOS :)
- // TODO: support floating point.
-
char numbuf[NUMBUFSIZ];
uint32_t ptr = 0;
for (; *fmt; ++fmt) {
if (max_len && ptr >= max_len - 1) {
break;
}
-
+
if (*fmt != '%') {
buffer[ptr++] = *fmt;
continue;
// process width
int width = -1;
if (*fmt >= '1' && *fmt <= '9') {
- for (width = 0; *fmt >= '0' && *fmt <= '9'; ) {
+ for (width = 0; *fmt >= '0' && *fmt <= '9';) {
width = 10 * width + *fmt++ - '0';
}
} else if (*fmt == '*') {
if (*fmt == '.') {
++fmt;
if (*fmt >= '0' && *fmt <= '9') {
- for (precision = 0; *fmt >= '0' && *fmt <= '9'; ) {
+ for (precision = 0; *fmt >= '0' && *fmt <= '9';) {
precision = 10 * precision + *fmt++ - '0';
}
} else if (*fmt == '*') {
char* data = "";
again:
switch (*fmt) {
- case 'l':
- case 'z':
- length = 1;
- ++fmt;
- goto again;
- case 'd':
- case 'i': {
- long x = length ? va_arg(vargs, long) : va_arg(vargs, int);
- int negative = x < 0 ? FLAG_NEGATIVE : 0;
- num = negative ? -x : x;
- flags |= FLAG_NUMERIC | FLAG_SIGNED | negative;
- break;
- }
- case 'u':
- format_unsigned:
- num = length ? va_arg(vargs, unsigned long) : va_arg(vargs, unsigned);
- flags |= FLAG_NUMERIC;
- break;
- case 'x':
- base = 16;
- goto format_unsigned;
- case 'X':
- flags = flags | FLAG_CAPS;
- base = 16;
- goto format_unsigned;
- case 'p':
- num = (uintptr_t) va_arg(vargs, void*);
- base = 16;
- flags |= FLAG_ALT | FLAG_ALT2 | FLAG_NUMERIC;
- break;
- case 's':
- data = va_arg(vargs, char*);
- break;
- case 'c':
- data = numbuf;
- numbuf[0] = va_arg(vargs, int);
- numbuf[1] = '\0';
- break;
- default:
- data = numbuf;
- numbuf[0] = (*fmt ? *fmt : '%');
- numbuf[1] = '\0';
- if (!*fmt) {
- fmt--;
+ case 'l':
+ case 'z':
+ length = 1;
+ ++fmt;
+ goto again;
+ case 'd':
+ case 'i': {
+ long x = length ? va_arg(vargs, long) : va_arg(vargs, int);
+ int negative = x < 0 ? FLAG_NEGATIVE : 0;
+ num = negative ? -x : x;
+ flags |= FLAG_NUMERIC | FLAG_SIGNED | negative;
+ break;
}
- break;
+ case 'u':
+ format_unsigned:
+ num = length ? va_arg(vargs, unsigned long)
+ : va_arg(vargs, unsigned);
+ flags |= FLAG_NUMERIC;
+ break;
+ case 'x':
+ base = 16;
+ goto format_unsigned;
+ case 'X':
+ flags = flags | FLAG_CAPS;
+ base = 16;
+ goto format_unsigned;
+ case 'p':
+ num = (uintptr_t)va_arg(vargs, void*);
+ base = 16;
+ flags |= FLAG_ALT | FLAG_ALT2 | FLAG_NUMERIC;
+ break;
+ case 's':
+ data = va_arg(vargs, char*);
+ break;
+ case 'c':
+ data = numbuf;
+ numbuf[0] = va_arg(vargs, int);
+ numbuf[1] = '\0';
+ break;
+ default:
+ data = numbuf;
+ numbuf[0] = (*fmt ? *fmt : '%');
+ numbuf[1] = '\0';
+ if (!*fmt) {
+ fmt--;
+ }
+ break;
}
if (flags & FLAG_NUMERIC) {
data = itoa(num, numbuf, base);
int i = 0;
char c;
- while ((flags & FLAG_CAPS) && (c = data[i]))
- {
+ while ((flags & FLAG_CAPS) && (c = data[i])) {
data[i] = c & ~((c & 0x40) >> 1);
i++;
}
} else if (flags & FLAG_SPACEPOSITIVE) {
prefix = " ";
}
- } else if ((flags & FLAG_NUMERIC) && (flags & FLAG_ALT)
- && (base == 16 || base == -16)
- && (num || (flags & FLAG_ALT2))) {
+ } else if ((flags & FLAG_NUMERIC) && (flags & FLAG_ALT) &&
+ (base == 16 || base == -16) &&
+ (num || (flags & FLAG_ALT2))) {
prefix = "0x";
}
int zeros;
if ((flags & FLAG_NUMERIC) && precision >= 0) {
zeros = precision > len ? precision - len : 0;
- } else if ((flags & FLAG_NUMERIC) && (flags & FLAG_ZERO)
- && !(flags & FLAG_LEFTJUSTIFY)
- && len + (int) strlen(prefix) < width) {
+ } else if ((flags & FLAG_NUMERIC) && (flags & FLAG_ZERO) &&
+ !(flags & FLAG_LEFTJUSTIFY) &&
+ len + (int)strlen(prefix) < width) {
zeros = width - len - strlen(prefix);
} else {
zeros = 0;
}
}
buffer[ptr++] = '\0';
+
+ return ptr;
}
-void
+size_t
sprintf(char* buffer, char* fmt, ...)
{
va_list args;
va_start(args, fmt);
- __sprintf_internal(buffer, fmt, 0, args);
+ size_t len = __sprintf_internal(buffer, fmt, 0, args);
va_end(args);
+ return len;
}
-void
+size_t
snprintf(char* buffer, size_t n, char* fmt, ...)
{
va_list args;
va_start(args, fmt);
- __sprintf_internal(buffer, fmt, n, args);
+ size_t len = __sprintf_internal(buffer, fmt, n, args);
va_end(args);
+ return len;
}
\ No newline at end of file