@@ -1,123 +1,214 @@
|
||||
/*
|
||||
* Copyright (c) 2019-2020 shchmue
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "sprintf.h"
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2019-2022 CTCaer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
|
||||
static void _putc(char *buffer, const char c) {
|
||||
*buffer = c;
|
||||
#include <utils/types.h>
|
||||
|
||||
char **sout_buf;
|
||||
|
||||
static void _s_putc(char c)
|
||||
{
|
||||
**sout_buf = c;
|
||||
*sout_buf += 1;
|
||||
}
|
||||
|
||||
static u32 _puts(char *buffer, const char *s) {
|
||||
u32 count = 0;
|
||||
for (; *s; s++, count++)
|
||||
_putc(buffer + count, *s);
|
||||
return count;
|
||||
static void _s_puts(char *s)
|
||||
{
|
||||
for (; *s; s++)
|
||||
_s_putc(*s);
|
||||
}
|
||||
|
||||
static u32 _putn(char *buffer, u32 v, int base, char fill, int fcnt) {
|
||||
char buf[0x121];
|
||||
static const char digits[] = "0123456789abcdefghijklmnopqrstuvwxyz";
|
||||
char *p;
|
||||
int c = fcnt;
|
||||
static void _s_putn(u32 v, int base, char fill, int fcnt)
|
||||
{
|
||||
static const char digits[] = "0123456789ABCDEF";
|
||||
|
||||
if (base > 36)
|
||||
return 0;
|
||||
char *p;
|
||||
char buf[65];
|
||||
int c = fcnt;
|
||||
bool negative = false;
|
||||
|
||||
p = buf + 0x120;
|
||||
*p = 0;
|
||||
do {
|
||||
c--;
|
||||
*--p = digits[v % base];
|
||||
v /= base;
|
||||
} while (v);
|
||||
if (base != 10 && base != 16)
|
||||
return;
|
||||
|
||||
if (fill != 0) {
|
||||
while (c > 0) {
|
||||
*--p = fill;
|
||||
c--;
|
||||
}
|
||||
}
|
||||
// Account for negative numbers.
|
||||
if (base == 10 && v & 0x80000000)
|
||||
{
|
||||
negative = true;
|
||||
v = (int)v * -1;
|
||||
c--;
|
||||
}
|
||||
|
||||
return _puts(buffer, p);
|
||||
p = buf + 64;
|
||||
*p = 0;
|
||||
do
|
||||
{
|
||||
c--;
|
||||
*--p = digits[v % base];
|
||||
v /= base;
|
||||
} while (v);
|
||||
|
||||
if (negative)
|
||||
*--p = '-';
|
||||
|
||||
if (fill != 0)
|
||||
{
|
||||
while (c > 0 && p > buf)
|
||||
{
|
||||
*--p = fill;
|
||||
c--;
|
||||
}
|
||||
}
|
||||
|
||||
_s_puts(p);
|
||||
}
|
||||
|
||||
u32 s_printf(char *buffer, const char *fmt, ...) {
|
||||
va_list ap;
|
||||
int fill, fcnt;
|
||||
u32 count = 0;
|
||||
void s_printf(char *out_buf, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
int fill, fcnt;
|
||||
|
||||
va_start(ap, fmt);
|
||||
while(*fmt) {
|
||||
if (*fmt == '%') {
|
||||
fmt++;
|
||||
fill = 0;
|
||||
fcnt = 0;
|
||||
if ((*fmt >= '0' && *fmt <= '9') || *fmt == ' ') {
|
||||
fcnt = *fmt;
|
||||
fmt++;
|
||||
if (*fmt >= '0' && *fmt <= '9') {
|
||||
fill = fcnt;
|
||||
fcnt = *fmt - '0';
|
||||
fmt++;
|
||||
} else {
|
||||
fill = ' ';
|
||||
fcnt -= '0';
|
||||
}
|
||||
}
|
||||
switch (*fmt) {
|
||||
case 'c':
|
||||
_putc(buffer + count, va_arg(ap, u32));
|
||||
count++;
|
||||
break;
|
||||
case 's':
|
||||
count += _puts(buffer + count, va_arg(ap, char *));
|
||||
break;
|
||||
case 'd':
|
||||
count += _putn(buffer + count, va_arg(ap, u32), 10, fill, fcnt);
|
||||
break;
|
||||
case 'p':
|
||||
case 'P':
|
||||
case 'x':
|
||||
case 'X':
|
||||
count += _putn(buffer + count, va_arg(ap, u32), 16, fill, fcnt);
|
||||
break;
|
||||
case '%':
|
||||
_putc(buffer + count, '%');
|
||||
count++;
|
||||
break;
|
||||
case '\0':
|
||||
goto out;
|
||||
default:
|
||||
_putc(buffer + count, '%');
|
||||
count++;
|
||||
_putc(buffer + count, *fmt);
|
||||
count++;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
_putc(buffer + count, *fmt);
|
||||
count++;
|
||||
}
|
||||
fmt++;
|
||||
}
|
||||
sout_buf = &out_buf;
|
||||
|
||||
out:
|
||||
buffer[count] = 0;
|
||||
va_end(ap);
|
||||
return count;
|
||||
}
|
||||
va_start(ap, fmt);
|
||||
while (*fmt)
|
||||
{
|
||||
if (*fmt == '%')
|
||||
{
|
||||
fmt++;
|
||||
fill = 0;
|
||||
fcnt = 0;
|
||||
if ((*fmt >= '0' && *fmt <= '9') || *fmt == ' ')
|
||||
{
|
||||
fcnt = *fmt;
|
||||
fmt++;
|
||||
if (*fmt >= '0' && *fmt <= '9')
|
||||
{
|
||||
fill = fcnt;
|
||||
fcnt = *fmt - '0';
|
||||
fmt++;
|
||||
}
|
||||
else
|
||||
{
|
||||
fill = ' ';
|
||||
fcnt -= '0';
|
||||
}
|
||||
}
|
||||
switch (*fmt)
|
||||
{
|
||||
case 'c':
|
||||
_s_putc(va_arg(ap, u32));
|
||||
break;
|
||||
case 's':
|
||||
_s_puts(va_arg(ap, char *));
|
||||
break;
|
||||
case 'd':
|
||||
_s_putn(va_arg(ap, u32), 10, fill, fcnt);
|
||||
break;
|
||||
case 'p':
|
||||
case 'P':
|
||||
case 'x':
|
||||
case 'X':
|
||||
_s_putn(va_arg(ap, u32), 16, fill, fcnt);
|
||||
break;
|
||||
case '%':
|
||||
_s_putc('%');
|
||||
break;
|
||||
case '\0':
|
||||
goto out;
|
||||
default:
|
||||
_s_putc('%');
|
||||
_s_putc(*fmt);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
_s_putc(*fmt);
|
||||
fmt++;
|
||||
}
|
||||
|
||||
out:
|
||||
**sout_buf = '\0';
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
void s_vprintf(char *out_buf, const char *fmt, va_list ap)
|
||||
{
|
||||
int fill, fcnt;
|
||||
|
||||
sout_buf = &out_buf;
|
||||
|
||||
while (*fmt)
|
||||
{
|
||||
if (*fmt == '%')
|
||||
{
|
||||
fmt++;
|
||||
fill = 0;
|
||||
fcnt = 0;
|
||||
if ((*fmt >= '0' && *fmt <= '9') || *fmt == ' ')
|
||||
{
|
||||
fcnt = *fmt;
|
||||
fmt++;
|
||||
if (*fmt >= '0' && *fmt <= '9')
|
||||
{
|
||||
fill = fcnt;
|
||||
fcnt = *fmt - '0';
|
||||
fmt++;
|
||||
}
|
||||
else
|
||||
{
|
||||
fill = ' ';
|
||||
fcnt -= '0';
|
||||
}
|
||||
}
|
||||
switch(*fmt)
|
||||
{
|
||||
case 'c':
|
||||
_s_putc(va_arg(ap, u32));
|
||||
break;
|
||||
case 's':
|
||||
_s_puts(va_arg(ap, char *));
|
||||
break;
|
||||
case 'd':
|
||||
_s_putn(va_arg(ap, u32), 10, fill, fcnt);
|
||||
break;
|
||||
case 'p':
|
||||
case 'P':
|
||||
case 'x':
|
||||
case 'X':
|
||||
_s_putn(va_arg(ap, u32), 16, fill, fcnt);
|
||||
break;
|
||||
case '%':
|
||||
_s_putc('%');
|
||||
break;
|
||||
case '\0':
|
||||
goto out;
|
||||
default:
|
||||
_s_putc('%');
|
||||
_s_putc(*fmt);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
_s_putc(*fmt);
|
||||
fmt++;
|
||||
}
|
||||
|
||||
out:
|
||||
**sout_buf = '\0';
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user