Login
Username:

Password:

Remember me



Lost Password?

Register now!
Sections
Who's Online
55 user(s) are online (41 user(s) are browsing Forums)

Members: 1
Guests: 54

saimo, more...
Support us!
Recent OS4 Files
OS4Depot.net
Report message:*
 

vswprintf implementation (need floating point support)

Subject: vswprintf implementation (need floating point support)
by kas1e on 2019/8/27 8:10:00

@All

I have found 2 vswprintf() implementations which we can use for os4 : one done by Salas00 (in his new unrar port), there is:

#include <wchar.h>
#include <string.h>
#include <stdarg.h>

struct putchdata {
    
wchar_t *buffer;
    
size_t maxlencount;
};

static 
void reverse(char *strsize_t len) {
    if (
len 1) {
        
char *start str;
        
char *end str len 1;
        
char tmp;

        while (
start end) {
            
tmp = *end;
            *
end-- = *start;
            *
start++ = tmp;
        }
    }
}

static 
size_t itoa(unsigned numchar *dstunsigned baseint issignedint addplusint uppercase) {
    
int a uppercase 'A' 'a';
    
int negative 0;
    
char *dst;
    
size_t len;

    if (
num == 0) {
        *
'0';
        return 
1;
    }

    if (
issigned && (int)num && base == 10) {
        
negative 1;
        
num = -num;
    }

    while (
num 0) {
        
unsigned rem num base;
        
num /= base;
        *
d++ = (rem 9) ? (rem 10 a) : (rem '0');
    }

    if (
negative)
        *
d++ = '-';
    else if (
addplus)
        *
d++ = '+';

    
len dst;
    
reverse(dstlen);

    return 
len;
}

static 
size_t lltoa(unsigned long long numchar *dstunsigned baseint issignedint addplusint uppercase) {
    
int a uppercase 'A' 'a';
    
int negative 0;
    
char *dst;
    
size_t len;

    if (
num == 0) {
        *
'0';
        return 
1;
    }

    if (
issigned && (signed long long)num && base == 10) {
        
negative 1;
        
num = -num;
    }

    while (
num 0) {
        
unsigned rem num base;
        
num /= base;
        *
d++ = (rem 9) ? (rem 10 a) : (rem '0');
    }

    if (
negative)
        *
d++ = '-';
    else if (
addplus)
        *
d++ = '+';

    
len dst;
    
reverse(dstlen);

    return 
len;
}

static 
void putchproc(wchar_t chstruct putchdata *pcd) {
    
size_t index pcd->count;

    if (
ch != '')
        
pcd->count++;

    if (
pcd->count pcd->maxlen)
        return;

    if (
pcd->count == pcd->maxlen) {
        
pcd->buffer[index] =  '';
        return;
    }

    
pcd->buffer[index] = ch;
}

#define PUTCH(ch) putchproc((ch), &pcd)

int vswprintf(wchar_t *buffersize_t maxlen, const wchar_t *fmtva_list ap) {
    
struct putchdata pcd;
    
wchar_t ch;
    const 
wchar_t *src;
    
char tmp[128];
    const 
char *hsrc;

    
pcd.buffer buffer;
    
pcd.maxlen maxlen;
    
pcd.count 0;

    while ((
ch = *fmt++) != '') {
        if (
ch == '%') {
            
int left 0;
            
int addplus 0;
            
int alternate 0;
            
int padzeros 0;
            
size_t width 0;
            
size_t limit 0;
            
int longlong 0;
            
int half 0;
            
size_t leni;
            
int uppercase;
            
void *ptr;
            const 
wchar_t *start fmt;

            if ((
ch = *fmt++) == '')
                goto 
out;

            for (;;) {
                if (
ch == '-')
                    
left 1;
                else if (
ch == '+')
                    
addplus 1;
                else if (
ch == '#')
                    
alternate 1;
                else if (
ch == '0')
                    
padzeros 1;
                else
                    break;

                if ((
ch = *fmt++) == '')
                    goto 
out;
            }

            while (
ch >= '0' && ch <= '9') {
                
width 10 width + (ch '0');

                if ((
ch = *fmt++) == '')
                    goto 
out;
            }

            if (
ch == '.') {
                if ((
ch = *fmt++) == '')
                    goto 
out;

                if (
ch == '*') {
                    
limit va_arg(apsize_t);

                    if ((
ch = *fmt++) == '')
                        goto 
out;
                } else {
                    while (
ch >= '0' && ch <= '9') {
                        
limit 10 limit + (ch '0');

                        if ((
ch = *fmt++) == '')
                            goto 
out;
                    }
                }
            }

            if (
ch == 'L') {
                
longlong 1;

                if ((
ch = *fmt++) == '')
                    goto 
out;
            } else if (
ch == 'l') {
                if ((
ch = *fmt++) == '')
                    goto 
out;

                if (
ch == 'l') {
                    
longlong 1;

                    if ((
ch = *fmt++) == '')
                        goto 
out;
                }
            } else if (
ch == 'h') {
                
half 1;

                if ((
ch = *fmt++) == '')
                    goto 
out;
            }

            switch (
ch) {
                default:
                    
fmt start;
                    
/* Fall through */
                
case '%':
                    
PUTCH('%');
                    break;
                case 
'C':
                case 
'c':
                    
PUTCH(va_arg(apwchar_t));
                    break;
                case 
'D':
                case 
'd':
                    
uppercase = (ch == 'D');
                    if (
longlong)
                        
len lltoa(va_arg(aplong long), tmp101addplusuppercase);
                    else
                        
len itoa(va_arg(apint), tmp101addplusuppercase);

                    
hsrc tmp;

                    if (
width len)
                        
width -= len;
                    else
                        
width 0;

                    if (
left == 0) {
                        for (
0widthi++) PUTCH(padzeros '0' ' ');
                    }

                    for (
0leni++) PUTCH(hsrc[i]);

                    if (
left != 0) {
                        for (
0widthi++) PUTCH(' ');
                    }
                    break;
                case 
'U':
                case 
'u':
                    
uppercase = (ch == 'U');
                    if (
longlong)
                        
len lltoa(va_arg(apunsigned long long), tmp100addplusuppercase);
                    else
                        
len itoa(va_arg(apunsigned int), tmp100addplusuppercase);

                    
hsrc tmp;

                    if (
width len)
                        
width -= len;
                    else
                        
width 0;

                    if (
left == 0) {
                        for (
0widthi++) PUTCH(padzeros '0' ' ');
                    }

                    for (
0leni++) PUTCH(hsrc[i]);

                    if (
left != 0) {
                        for (
0widthi++) PUTCH(' ');
                    }
                    break;
                case 
'X':
                case 
'x':
                    
uppercase = (ch == 'X');
                    if (
longlong)
                        
len lltoa(va_arg(apunsigned long long), tmp160addplusuppercase);
                    else
                        
len itoa(va_arg(apunsigned int), tmp160addplusuppercase);

                    
hsrc tmp;

                    if (
width len)
                        
width -= len;
                    else
                        
width 0;

                    if (
left == 0) {
                        for (
0widthi++) PUTCH(padzeros '0' ' ');
                    }

                    for (
0leni++) PUTCH(hsrc[i]);

                    if (
left != 0) {
                        for (
0widthi++) PUTCH(' ');
                    }
                    break;
                case 
'P':
                case 
'p':
                    
uppercase = (ch == 'P');
                    
ptr va_arg(apvoid *);
                    
len itoa((unsigned)ptrtmp1600uppercase);

                    
hsrc tmp;
                    
width 8;

                    if (
width len)
                        
width -= len;
                    else
                        
width 0;

                    if (
alternate && ptr != NULL) {
                        
PUTCH('0');
                        
PUTCH('x');
                    }

                    for (
0widthi++) PUTCH('0');

                    for (
0leni++) PUTCH(hsrc[i]);
                    break;
                case 
'S':
                case 
's':
                    if (
half) {
                        
hsrc va_arg(ap, const char *);
                        if (
hsrc == NULL)
                            
hsrc "(null)";

                        
len strlen(hsrc);

                        if (
limit && len limit)
                            
len limit;

                        if (
width len)
                            
width -= len;
                        else
                            
width 0;

                        if (
left == 0) {
                            for (
0widthi++) PUTCH(' ');
                        }

                        for (
0leni++) PUTCH(hsrc[i]);

                        if (
left != 0) {
                            for (
0widthi++) PUTCH(' ');
                        }
                    } else {
                        
src va_arg(ap, const wchar_t *);
                        if (
src == NULL)
                            
src L"(null)";

                        
len wcslen(src);

                        if (
limit && len limit)
                            
len limit;

                        if (
width len)
                            
width -= len;
                        else
                            
width 0;

                        if (
left == 0) {
                            for (
0widthi++) PUTCH(' ');
                        }

                        for (
0leni++) PUTCH(src[i]);

                        if (
left != 0) {
                            for (
0widthi++) PUTCH(' ');
                        }
                    }
                    break;
            }
        } else {
            
PUTCH(ch);
        }
    }

out:

    
PUTCH('');

    return 
pcd.count;
}

int swprintf(wchar_t *buffersize_t maxlen, const wchar_t *fmt, ...) {
    
va_list ap;
    
int wc;

    
va_start(apfmt);
    
wc vswprintf(buffermaxlenfmtap);
    
va_end(ap);

    return 
wc;
}


And another one i use since some time done by AROS team, there is:

#include <stdarg.h>
#include <stdlib.h>
#include <ctype.h>
#include <wchar.h>
#include <wctype.h>
#include <limits.h>
#include <string.h>


#define ZEROPAD    1        /* pad with zero */
#define SIGN    2        /* unsigned/signed long */
#define PLUS    4        /* show plus */
#define SPACE    8        /* space if plus */
#define LEFT    16        /* left justified */
#define SPECIAL    32        /* 0x */
#define LARGE    64        /* use 'ABCDEF' instead of 'abcdef' */


#define do_div(n,base) ({ 
int __res
__res = ((unsigned long longn) % (unsignedbase
= ((unsigned long longn) / (unsignedbase
__res; })


static 
int skip_atoi(const wchar_t **s)
{
    
int i=0;

    while (
iswdigit(**s))
        
i*10 + *((*s)++) - L'0';
    return 
i;
}


static 
wchar_t *
number (wchar_t *strlong long numint baseint sizeint precision,
    
int type)
{
   
wchar_t c,sign,tmp[66];
   const 
wchar_t *digits L"0123456789abcdefghijklmnopqrstuvwxyz";
   
int i;
   
   if (
type LARGE)
     
digits L"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
   if (
type LEFT)
     
type &= ~ZEROPAD;
   if (
base || base 36)
     return 
0;
   
   
= (type ZEROPAD) ? L'0' L' ';
   
sign 0;
   
   if (
type SIGN
     {
    if (
num 0
      {
         
sign L'-';
         
num = -num;
         
size--;
      } 
    else if (
type PLUS
      {
         
sign L'+';
         
size--;
      } 
    else if (
type SPACE
      {
         
sign L' ';
         
size--;
      }
     }
   
   if (
type SPECIAL
     {
    if (
base == 16)
      
size -= 2;
    else if (
base == 8)
      
size--;
     }
   
   
0;
   if (
num == 0)
     
tmp[i++]='0';
   else while (
num != 0)
     
tmp[i++] = digits[do_div(num,base)];
   if (
precision)
     
precision i;
   
size -= precision;
   if (!(
type&(ZEROPAD+LEFT)))
     while(
size-->0)
       *
str++ = L' ';
   if (
sign)
     *
str++ = sign;
   if (
type SPECIAL)
     {
    if (
base==8)
      {
         *
str++ = L'0';
      }
    else if (
base==16
      {
         *
str++ = L'0';
         *
str++ = digits[33];
      }
     }
   if (!(
type LEFT))
     while (
size-- > 0)
       *
str++ = c;
   while (
precision--)
     *
str++ = '0';
   while (
i-- > 0)
     *
str++ = tmp[i];
   while (
size-- > 0)
     *
str++ = L' ';
   return 
str;
}


int _vsnwprintf(wchar_t *bufsize_t cnt, const wchar_t *fmtva_list args)
{
    
int len;
    
unsigned long long num;
    
int ibase;
    
wchar_t str;
    const 
char *s;
    const 
wchar_t *sw;

    
int flags;        /* flags to number() */

    
int field_width;    /* width of output field */
    
int precision;        /* min. # of digits for integers; max
                   number of chars for from string */
    
int qualifier;        /* 'h', 'l', 'L', 'w' or 'I' for integer fields */

    
for (str=buf ; *fmt ; ++fmt) {
        if (*
fmt != L'%') {
            *
str++ = *fmt;
            continue;
        }

        
/* process flags */
        
flags 0;
        
repeat:
            ++
fmt;        /* this also skips first '%' */
            
switch (*fmt) {
                case 
L'-'flags |= LEFT; goto repeat;
                case 
L'+'flags |= PLUS; goto repeat;
                case 
L' 'flags |= SPACE; goto repeat;
                case 
L'#'flags |= SPECIAL; goto repeat;
                case 
L'0'flags |= ZEROPAD; goto repeat;
            }

        
/* get field width */
        
field_width = -1;
        if (
iswdigit(*fmt))
            
field_width skip_atoi(&fmt);
        else if (*
fmt == L'*') {
            ++
fmt;
            
/* it's the next argument */
            
field_width va_arg(argsint);
            if (
field_width 0) {
                
field_width = -field_width;
                
flags |= LEFT;
            }
        }

        
/* get the precision */
        
precision = -1;
        if (*
fmt == L'.') {
            ++
fmt;    
            if (
iswdigit(*fmt))
                
precision skip_atoi(&fmt);
            else if (*
fmt == L'*') {
                ++
fmt;
                
/* it's the next argument */
                
precision va_arg(argsint);
            }
            if (
precision 0)
                
precision 0;
        }

        
/* get the conversion qualifier */
        
qualifier = -1;
        if (*
fmt == 'h' || *fmt == 'l' || *fmt == 'L' || *fmt == 'w') {
            
qualifier = *fmt;
            ++
fmt;
        } else if (*
fmt == 'I' && *(fmt+1) == '6' && *(fmt+2) == '4') {
            
qualifier = *fmt;
            
fmt += 3;
        }

        
/* default base */
        
base 10;

        switch (*
fmt) {
        case 
L'c':
            if (!(
flags LEFT))
                while (--
field_width 0)
                    *
str++ = L' ';
            if (
qualifier == 'h')
                *
str++ = (wchar_tva_arg(argsint);
            else
                *
str++ = (wchar_tva_arg(argsint);
            while (--
field_width 0)
                *
str++ = L' ';
            continue;

        case 
L'C':
            if (!(
flags LEFT))
                while (--
field_width 0)
                    *
str++ = L' ';
            if (
qualifier == 'l' || qualifier == 'w')
                *
str++ = (wchar_tva_arg(argsint);
            else
                *
str++ = (wchar_tva_arg(argsint);
            while (--
field_width 0)
                *
str++ = L' ';
            continue;

        case 
L's':
            if (
qualifier == 'h') {
                
/* print ascii string */
                
va_arg(argschar *);
                if (
== NULL)
                    
"<NULL>";

                
len strlen (s);
                if ((
unsigned int)len > (unsigned int)precision)
                    
len precision;

                if (!(
flags LEFT))
                    while (
len field_width--)
                        *
str++ = L' ';
                for (
0len; ++i)
                    *
str++ = (wchar_t)(*s++);
                while (
len field_width--)
                    *
str++ = L' ';
            } else {
                
/* print unicode string */
                
sw va_arg(argswchar_t *);
                if (
sw == NULL)
                    
sw L"<NULL>";

                
len wcslen (sw);
                if ((
unsigned int)len > (unsigned int)precision)
                    
len precision;

                if (!(
flags LEFT))
                    while (
len field_width--)
                        *
str++ = L' ';
                for (
0len; ++i)
                    *
str++ = *sw++;
                while (
len field_width--)
                    *
str++ = L' ';
            }
            continue;

        case 
L'S':
            if (
qualifier == 'l' || qualifier == 'w') {
                
/* print unicode string */
                
sw va_arg(argswchar_t *);
                if (
sw == NULL)
                    
sw L"<NULL>";

                
len wcslen (sw);
                if ((
unsigned int)len > (unsigned int)precision)
                    
len precision;

                if (!(
flags LEFT))
                    while (
len field_width--)
                        *
str++ = L' ';
                for (
0len; ++i)
                    *
str++ = *sw++;
                while (
len field_width--)
                    *
str++ = L' ';
            } else {
                
/* print ascii string */
                
va_arg(argschar *);
                if (
== NULL)
                    
"<NULL>";

                
len strlen (s);
                if ((
unsigned int)len > (unsigned int)precision)
                    
len precision;

                if (!(
flags LEFT))
                    while (
len field_width--)
                        *
str++ = L' ';
                for (
0len; ++i)
                    *
str++ = (wchar_t)(*s++);
                while (
len field_width--)
                    *
str++ = L' ';
            }
            continue;
        case 
L'p':
            if (
field_width == -1) {
                
field_width 2*sizeof(void *);
                
flags |= ZEROPAD;
            }
            
str number(str,
                (
unsigned longva_arg(argsvoid *), 16,
                
field_widthprecisionflags);
            continue;

        case 
L'n':
            if (
qualifier == 'l') {
                
long ip va_arg(argslong *);
                *
ip = (str buf);
            } else {
                
int ip va_arg(argsint *);
                *
ip = (str buf);
            }
            continue;

        
/* integer number formats - set up the flags and "break" */
        
case L'o':
            
base 8;
            break;

        case 
L'b':
            
base 2;
            break;

        case 
L'X':
            
flags |= LARGE;
        case 
L'x':
            
base 16;
            break;

        case 
L'd':
        case 
L'i':
            
flags |= SIGN;
        case 
L'u':
            break;

        default:
            if (*
fmt != L'%')
                *
str++ = L'%';
            if (*
fmt)
                *
str++ = *fmt;
            else
                --
fmt;
            continue;
        }

        if (
qualifier == 'I')
            
num va_arg(argsunsigned long long);
        else if (
qualifier == 'l')
            
num va_arg(argsunsigned long);
        else if (
qualifier == 'h') {
            if (
flags SIGN)
                
num va_arg(argsint);
            else
                
num va_arg(argsunsigned int);
        }
        else {
            if (
flags SIGN)
                
num va_arg(argsint);
            else
                
num va_arg(argsunsigned int);
        }
        
str number(strnumbasefield_widthprecisionflags);
    }
    *
str L'';
    return 
str-buf;
}


int swprintf(wchar_t *bufsize_t n,const wchar_t *fmt, ...)
{
    
va_list args;
    
int i;

    
va_start(argsfmt);
    
i=_vsnwprintf(buf,n,fmt,args);
    
va_end(args);
    return 
i;
}


int _snwprintf(wchar_t *bufsize_t cnt, const wchar_t *fmt, ...)
{
    
va_list args;
    
int i;

    
va_start(argsfmt);
    
i=_vsnwprintf(buf,cnt,fmt,args);
    
va_end(args);
    return 
i;
}


int vswprintf(wchar_t *bufsize_t n, const wchar_t *fmtva_list args)
{
    return 
_vsnwprintf(buf,n,fmt,args);
}


Both of them working, but both of them didn't handle floating point. I.e. there in both realisations no case 'f': code, and
because of that , when i want to do something like this:

swprintf(tmp, 255, L"triangles:%0.3f mio/s", driver->getPrimitiveCountDrawn(1) * (1.f / 1000000.f));

Then instead of necessary value (which should be 0.xxxx), i have some random/garbage character.

Is there anyone who can wrote missing case 'f': in any of those examples ? I assume it will be just copy of case 'd' with some (?) little changes.

Checking google for different vsnwprintf() implementations didn't help much at moment.

Thanks !
Powered by XOOPS 2.0 © 2001-2016 The XOOPS Project