Skip to content

Commit 6770f9c

Browse files
authored
Update rt_vsnprintf_tiny.c
1 parent aee8920 commit 6770f9c

File tree

1 file changed

+182
-13
lines changed

1 file changed

+182
-13
lines changed

src/klibc/rt_vsnprintf_tiny.c

Lines changed: 182 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -276,12 +276,141 @@ static char *print_number(char *buf,
276276
return buf;
277277
}
278278

279-
#if (defined(__GNUC__) && !defined(__ARMCC_VERSION) /* GCC */) && (__GNUC__ >= 7)
280-
/* Disable "-Wimplicit-fallthrough" below GNUC V7 */
279+
#ifdef RT_USING_F_KPRINTF
280+
#define SZB_OUTPUT 32
281+
#define XF_DPC '.' /* Decimal separator for floating point */
282+
#ifndef isinf
283+
#define isinf(d) (isnan((d - d)) && !isnan(d))
284+
#endif
285+
#ifndef isnan
286+
#define isnan(d) (d != d)
287+
#endif
288+
// #include <math.h>
289+
static int ilog10 (double n) /* Calculate log10(n) in integer output */
290+
{
291+
int rv = 0;
292+
293+
while (n >= 10) { /* Decimate digit in right shift */
294+
if (n >= 100000) {
295+
n /= 100000; rv += 5;
296+
} else {
297+
n /= 10; rv++;
298+
}
299+
}
300+
while (n < 1) { /* Decimate digit in left shift */
301+
if (n < 0.00001) {
302+
n *= 100000; rv -= 5;
303+
} else {
304+
n *= 10; rv--;
305+
}
306+
}
307+
return rv;
308+
}
309+
310+
static double i10x (int n) /* Calculate 10^n */
311+
{
312+
double rv = 1;
313+
314+
while (n > 0) { /* Left shift */
315+
if (n >= 5) {
316+
rv *= 100000; n -= 5;
317+
} else {
318+
rv *= 10; n--;
319+
}
320+
}
321+
while (n < 0) { /* Right shift */
322+
if (n <= -5) {
323+
rv /= 100000; n += 5;
324+
} else {
325+
rv /= 10; n++;
326+
}
327+
}
328+
return rv;
329+
}
330+
static void ftoa (
331+
char* buf, /* Buffer to output the generated string */
332+
double val, /* Real number to output */
333+
int prec, /* Number of fractinal digits */
334+
char fmt /* Notation */
335+
)
336+
{
337+
int d;
338+
int e = 0, m = 0;
339+
char sign = 0;
340+
double w;
341+
const char *er = 0;
342+
343+
344+
if (isnan(val)) { /* Not a number? */
345+
er = "NaN";
346+
} else {
347+
if (prec < 0) prec = 6; /* Default precision (6 fractional digits) */
348+
if (val < 0) { /* Nagative value? */
349+
val = -val; sign = '-';
350+
} else {
351+
sign = '+';
352+
}
353+
if (isinf(val)) { /* Infinite? */
354+
er = "INF";
355+
} else {
356+
if (fmt == 'f') { /* Decimal notation? */
357+
val += i10x(-prec) / 2; /* Round (nearest) */
358+
m = ilog10(val);
359+
if (m < 0) m = 0;
360+
if (m + prec + 3 >= SZB_OUTPUT) er = "OV"; /* Buffer overflow? */
361+
} else { /* E notation */
362+
if (val != 0) { /* Not a true zero? */
363+
val += i10x(ilog10(val) - prec) / 2; /* Round (nearest) */
364+
e = ilog10(val);
365+
if (e > 99 || prec + 6 >= SZB_OUTPUT) { /* Buffer overflow or E > +99? */
366+
er = "OV";
367+
} else {
368+
if (e < -99) e = -99;
369+
val /= i10x(e); /* Normalize */
370+
}
371+
}
372+
}
373+
}
374+
if (!er) { /* Not error condition */
375+
if (sign == '-') *buf++ = sign; /* Add a - if negative value */
376+
do { /* Put decimal number */
377+
w = i10x(m); /* Snip the highest digit d */
378+
d = val / w; val -= d * w;
379+
if (m == -1) *buf++ = XF_DPC; /* Insert a decimal separarot if get into fractional part */
380+
*buf++ = '0' + d; /* Put the digit */
381+
} while (--m >= -prec); /* Output all digits specified by prec */
382+
if (fmt != 'f') { /* Put exponent if needed */
383+
*buf++ = fmt;
384+
if (e < 0) {
385+
e = -e; *buf++ = '-';
386+
} else {
387+
*buf++ = '+';
388+
}
389+
*buf++ = '0' + e / 10;
390+
*buf++ = '0' + e % 10;
391+
}
392+
}
393+
}
394+
if (er) { /* Error condition? */
395+
if (sign) *buf++ = sign; /* Add sign if needed */
396+
do *buf++ = *er++; while (*er); /* Put error symbol */
397+
}
398+
*buf = 0; /* Term */
399+
}
400+
401+
char *print_float(double value)
402+
{
403+
static char buff[26] = {0};
404+
ftoa(buff, value, 6, 'f');
405+
return buff;
406+
}
407+
#endif
408+
409+
#if defined(__GNUC__) && !defined(__ARMCC_VERSION) /* GCC */
281410
#pragma GCC diagnostic push
282411
/* ignore warning: this statement may fall through */
283412
#pragma GCC diagnostic ignored "-Wimplicit-fallthrough"
284-
#endif /* (defined(__GNUC__) && !defined(__ARMCC_VERSION)) && (__GNUC__ >= 7 */
413+
#endif /* defined(__GNUC__) && !defined(__ARMCC_VERSION) */
285414
/**
286415
* @brief This function will fill a formatted string to buffer.
287416
*
@@ -295,13 +424,13 @@ static char *print_number(char *buf,
295424
*
296425
* @return The number of characters actually written to buffer.
297426
*/
298-
int rt_vsnprintf(char *buf, rt_size_t size, const char *fmt, va_list args)
427+
rt_weak int rt_vsnprintf(char *buf, rt_size_t size, const char *fmt, va_list args)
299428
{
300-
#ifdef RT_KLIBC_USING_VSNPRINTF_LONGLONG
429+
#ifdef RT_KPRINTF_USING_LONGLONG
301430
unsigned long long num = 0;
302431
#else
303432
unsigned long num = 0;
304-
#endif /* RT_KLIBC_USING_VSNPRINTF_LONGLONG */
433+
#endif /* RT_KPRINTF_USING_LONGLONG */
305434
int i = 0, len = 0;
306435
char *str = RT_NULL, *end = RT_NULL, c = 0;
307436
const char *s = RT_NULL;
@@ -392,20 +521,20 @@ int rt_vsnprintf(char *buf, rt_size_t size, const char *fmt, va_list args)
392521
qualifier = 0; /* get the conversion qualifier */
393522

394523
if (*fmt == 'h' || *fmt == 'l' ||
395-
#ifdef RT_KLIBC_USING_VSNPRINTF_LONGLONG
524+
#ifdef RT_KPRINTF_USING_LONGLONG
396525
*fmt == 'L' ||
397-
#endif /* RT_KLIBC_USING_VSNPRINTF_LONGLONG */
526+
#endif /* RT_KPRINTF_USING_LONGLONG */
398527
*fmt == 'z')
399528
{
400529
qualifier = *fmt;
401530
++fmt;
402-
#ifdef RT_KLIBC_USING_VSNPRINTF_LONGLONG
531+
#ifdef RT_KPRINTF_USING_LONGLONG
403532
if (qualifier == 'l' && *fmt == 'l')
404533
{
405534
qualifier = 'L';
406535
++fmt;
407536
}
408-
#endif /* RT_KLIBC_USING_VSNPRINTF_LONGLONG */
537+
#endif /* RT_KPRINTF_USING_LONGLONG */
409538
if (qualifier == 'h' && *fmt == 'h')
410539
{
411540
qualifier = 'H';
@@ -448,7 +577,7 @@ int rt_vsnprintf(char *buf, rt_size_t size, const char *fmt, va_list args)
448577
s = va_arg(args, char *);
449578
if (!s)
450579
{
451-
s = "(null)";
580+
s = "(NULL)";
452581
}
453582

454583
for (len = 0; (len != field_width) && (s[len] != '\0'); len++);
@@ -527,7 +656,46 @@ int rt_vsnprintf(char *buf, rt_size_t size, const char *fmt, va_list args)
527656
case 'g':
528657
case 'f':
529658
case 'F':
659+
#ifndef RT_USING_F_KPRINTF
530660
va_arg(args, double);
661+
#else
662+
s = print_float(va_arg(args, double));
663+
field_width = rt_strlen(s);
664+
if (!s)
665+
{
666+
s = "(NULL)";
667+
}
668+
669+
for (len = 0; (len != field_width) && (s[len] != '\0'); len++);
670+
671+
if (precision > 0 && len > precision)
672+
{
673+
len = precision;
674+
}
675+
676+
if (!(flags & LEFT))
677+
{
678+
while (len < field_width--)
679+
{
680+
if (str < end) *str = ' ';
681+
++ str;
682+
}
683+
}
684+
685+
for (i = 0; i < len; ++i)
686+
{
687+
if (str < end) *str = *s;
688+
++ str;
689+
++ s;
690+
}
691+
692+
while (len < field_width--)
693+
{
694+
if (str < end) *str = ' ';
695+
++ str;
696+
}
697+
continue;
698+
#endif
531699
default:
532700
if (str < end)
533701
{
@@ -606,6 +774,7 @@ int rt_vsnprintf(char *buf, rt_size_t size, const char *fmt, va_list args)
606774
*/
607775
return str - buf;
608776
}
609-
#if (defined(__GNUC__) && !defined(__ARMCC_VERSION) /* GCC */) && (__GNUC__ >= 7)
777+
RTM_EXPORT(rt_vsnprintf);
778+
#if defined(__GNUC__) && !defined(__ARMCC_VERSION) /* GCC */
610779
#pragma GCC diagnostic pop /* ignored "-Wimplicit-fallthrough" */
611-
#endif /* (defined(__GNUC__) && !defined(__ARMCC_VERSION)) && (__GNUC__ >= 7 */
780+
#endif /* defined(__GNUC__) && !defined(__ARMCC_VERSION) */

0 commit comments

Comments
 (0)