Merge branch 'vfs-dev'
[lunaix-os.git] / lunaix-os / libs / klibc / stdio / sprintf.c
index a48ef1f0e9c37d0c061b04cbf9a64099e8a25f8b..d35706883ea8facc7ade8668a4a659859fb460ec 100644 (file)
@@ -8,34 +8,32 @@
 
 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;
@@ -55,7 +53,7 @@ __sprintf_internal(char* buffer, char* fmt, size_t max_len, va_list vargs)
         // 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 == '*') {
@@ -68,7 +66,7 @@ __sprintf_internal(char* buffer, char* fmt, size_t max_len, va_list vargs)
         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 == '*') {
@@ -87,60 +85,60 @@ __sprintf_internal(char* buffer, char* fmt, size_t max_len, va_list vargs)
         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++;
             }
@@ -155,9 +153,9 @@ __sprintf_internal(char* buffer, char* fmt, size_t max_len, va_list vargs)
             } 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";
         }
 
@@ -170,9 +168,9 @@ __sprintf_internal(char* buffer, char* fmt, size_t max_len, va_list vargs)
         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;
@@ -195,22 +193,26 @@ __sprintf_internal(char* buffer, char* fmt, size_t max_len, va_list vargs)
         }
     }
     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