enhanced xprintf
This commit is contained in:
parent
b70e378041
commit
35e9b1777f
@ -481,6 +481,12 @@ typedef qse_int_t qse_intptr_t;
|
|||||||
# define QSE_SIZEOF_FLTMAX_T QSE_SIZEOF_FLT_T
|
# define QSE_SIZEOF_FLTMAX_T QSE_SIZEOF_FLT_T
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/** @typedef qse_ptrdiff_t
|
||||||
|
*/
|
||||||
|
typedef qse_ssize_t qse_ptrdiff_t;
|
||||||
|
#define QSE_SIZEOF_PTRDIFF_T QSE_SIZEOF_SSIZE_T
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The qse_mchar_t type defines a multi-byte character type.
|
* The qse_mchar_t type defines a multi-byte character type.
|
||||||
*/
|
*/
|
||||||
|
@ -40,10 +40,11 @@ enum
|
|||||||
LF_J = (1 << 2),
|
LF_J = (1 << 2),
|
||||||
LF_L = (1 << 3),
|
LF_L = (1 << 3),
|
||||||
LF_Q = (1 << 4),
|
LF_Q = (1 << 4),
|
||||||
LF_Z = (1 << 5),
|
LF_T = (1 << 5),
|
||||||
|
LF_Z = (1 << 6),
|
||||||
|
|
||||||
/* long double */
|
/* long double */
|
||||||
LF_LD = (1 << 6)
|
LF_LD = (1 << 7)
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct
|
static struct
|
||||||
@ -71,7 +72,7 @@ static struct
|
|||||||
{ LF_Q, 0 }, /* q */
|
{ LF_Q, 0 }, /* q */
|
||||||
{ 0, 0 }, /* r */
|
{ 0, 0 }, /* r */
|
||||||
{ 0, 0 }, /* s */
|
{ 0, 0 }, /* s */
|
||||||
{ 0, 0 }, /* t */
|
{ LF_T, 0 }, /* t */
|
||||||
{ 0, 0 }, /* u */
|
{ 0, 0 }, /* u */
|
||||||
{ 0, 0 }, /* v */
|
{ 0, 0 }, /* v */
|
||||||
{ 0, 0 }, /* w */
|
{ 0, 0 }, /* w */
|
||||||
@ -97,6 +98,10 @@ enum
|
|||||||
};
|
};
|
||||||
|
|
||||||
#include <stdio.h> /* TODO: remove dependency on this */
|
#include <stdio.h> /* TODO: remove dependency on this */
|
||||||
|
#if defined(_MSC_VER) || defined(__BORLANDC__) || (defined(__WATCOMC__) && (__WATCOMC__ < 1200))
|
||||||
|
# define snprintf _snprintf
|
||||||
|
# define vsnprintf _vsnprintf
|
||||||
|
#endif
|
||||||
|
|
||||||
static int put_wchar (qse_wchar_t c, void *arg)
|
static int put_wchar (qse_wchar_t c, void *arg)
|
||||||
{
|
{
|
||||||
@ -186,8 +191,7 @@ int qse_mvprintf (const char_t* fmt, va_list ap)
|
|||||||
#define sprintn w_sprintn
|
#define sprintn w_sprintn
|
||||||
#define xprintf qse_wxprintf
|
#define xprintf qse_wxprintf
|
||||||
|
|
||||||
static const qse_wchar_t w_hex2ascii[] =
|
static const qse_wchar_t w_hex2ascii[] = QSE_WT("0123456789abcdefghijklmnopqrstuvwxyz");
|
||||||
QSE_WT("0123456789abcdefghijklmnopqrstuvwxyz");
|
|
||||||
#define hex2ascii(hex) (w_hex2ascii[hex])
|
#define hex2ascii(hex) (w_hex2ascii[hex])
|
||||||
|
|
||||||
#include "printf.h"
|
#include "printf.h"
|
||||||
|
@ -87,15 +87,15 @@ static char_t* sprintn (char_t* nbuf, qse_uintmax_t num, int base, int *lenp, in
|
|||||||
/* TODO: error check */
|
/* TODO: error check */
|
||||||
#define PUT_CHAR(c) do { \
|
#define PUT_CHAR(c) do { \
|
||||||
if (put_char (c, arg) <= -1) goto oops; \
|
if (put_char (c, arg) <= -1) goto oops; \
|
||||||
retval++; \
|
outcnt++; \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define PUT_OCHAR(c) do { \
|
#define PUT_OCHAR(c) do { \
|
||||||
if (put_ochar (c, arg) <= -1) goto oops; \
|
if (put_ochar (c, arg) <= -1) goto oops; \
|
||||||
retval++; \
|
outcnt++; \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
int xprintf (char_t const *fmt, int (*put_char)(char_t, void*), int (*put_ochar) (ochar_t, void*), void *arg, va_list ap)
|
int xprintf (const char_t* fmt, int (*put_char)(char_t, void*), int (*put_ochar) (ochar_t, void*), void *arg, va_list ap)
|
||||||
{
|
{
|
||||||
char_t nbuf[MAXNBUF];
|
char_t nbuf[MAXNBUF];
|
||||||
const char_t* p, * percent;
|
const char_t* p, * percent;
|
||||||
@ -105,18 +105,34 @@ int xprintf (char_t const *fmt, int (*put_char)(char_t, void*), int (*put_ochar)
|
|||||||
ochar_t oach, opadc, * osp;
|
ochar_t oach, opadc, * osp;
|
||||||
int lm_flag, lm_dflag, flagc, numlen;
|
int lm_flag, lm_dflag, flagc, numlen;
|
||||||
qse_uintmax_t num = 0;
|
qse_uintmax_t num = 0;
|
||||||
int stop = 0, retval = 0;
|
int stop = 0;
|
||||||
char_t fltbuf[100];
|
int outcnt = 0;
|
||||||
|
|
||||||
qse_mchar_t fltfmt[64];
|
struct
|
||||||
qse_mchar_t* fltfmtp = QSE_NULL;
|
{
|
||||||
qse_size_t fltfmtc;
|
qse_mchar_t sbuf[32];
|
||||||
|
qse_mchar_t* ptr;
|
||||||
|
qse_size_t capa;
|
||||||
|
} fltfmt;
|
||||||
|
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
char_t sbuf[96];
|
||||||
|
char_t* ptr;
|
||||||
|
qse_size_t capa;
|
||||||
|
} fltout;
|
||||||
|
|
||||||
|
fltfmt.ptr = fltfmt.sbuf;
|
||||||
|
fltfmt.capa = QSE_COUNTOF(fltfmt.sbuf) - 1;
|
||||||
|
|
||||||
|
fltout.ptr = fltout.sbuf;
|
||||||
|
fltout.capa = QSE_COUNTOF(fltout.sbuf) - 1;
|
||||||
|
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
while ((ch = (uchar_t)*fmt++) != T('%') || stop)
|
while ((ch = (uchar_t)*fmt++) != T('%') || stop)
|
||||||
{
|
{
|
||||||
if (ch == T('\0')) return retval;
|
if (ch == T('\0')) goto done;
|
||||||
PUT_CHAR(ch);
|
PUT_CHAR(ch);
|
||||||
}
|
}
|
||||||
percent = fmt - 1;
|
percent = fmt - 1;
|
||||||
@ -248,9 +264,7 @@ reswitch:
|
|||||||
case T('q'): /* long long int */
|
case T('q'): /* long long int */
|
||||||
case T('j'): /* uintmax_t */
|
case T('j'): /* uintmax_t */
|
||||||
case T('z'): /* size_t */
|
case T('z'): /* size_t */
|
||||||
#if 0
|
|
||||||
case T('t'): /* ptrdiff_t */
|
case T('t'): /* ptrdiff_t */
|
||||||
#endif
|
|
||||||
if (lm_flag & LF_LD) goto invalid_format;
|
if (lm_flag & LF_LD) goto invalid_format;
|
||||||
|
|
||||||
flagc |= FLAGC_LENMOD;
|
flagc |= FLAGC_LENMOD;
|
||||||
@ -293,31 +307,28 @@ reswitch:
|
|||||||
/* end of length modifiers */
|
/* end of length modifiers */
|
||||||
|
|
||||||
case T('n'):
|
case T('n'):
|
||||||
if (lm_flag & LF_J)
|
if (lm_flag & LF_J) /* j */
|
||||||
*(va_arg(ap, qse_intmax_t*)) = retval;
|
*(va_arg(ap, qse_intmax_t*)) = outcnt;
|
||||||
|
else if (lm_flag & LF_Z) /* z */
|
||||||
|
*(va_arg(ap, qse_size_t*)) = outcnt;
|
||||||
#if (QSE_SIZEOF_LONG_LONG > 0)
|
#if (QSE_SIZEOF_LONG_LONG > 0)
|
||||||
else if (lm_flag & LF_Q)
|
else if (lm_flag & LF_Q) /* ll */
|
||||||
*(va_arg(ap, long long int*)) = retval;
|
*(va_arg(ap, long long int*)) = outcnt;
|
||||||
#endif
|
#endif
|
||||||
else if (lm_flag & LF_L)
|
else if (lm_flag & LF_L) /* l */
|
||||||
*(va_arg(ap, long int*)) = retval;
|
*(va_arg(ap, long int*)) = outcnt;
|
||||||
else if (lm_flag & LF_Z)
|
else if (lm_flag & LF_H) /* h */
|
||||||
*(va_arg(ap, qse_size_t*)) = retval;
|
*(va_arg(ap, short int*)) = outcnt;
|
||||||
else if (lm_flag & LF_H)
|
else if (lm_flag & LF_C) /* hh */
|
||||||
*(va_arg(ap, short int*)) = retval;
|
*(va_arg(ap, char*)) = outcnt;
|
||||||
else if (lm_flag & LF_C)
|
|
||||||
*(va_arg(ap, char*)) = retval;
|
|
||||||
else
|
else
|
||||||
*(va_arg(ap, int*)) = retval;
|
*(va_arg(ap, int*)) = outcnt;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
||||||
/* signed integer conversions */
|
/* signed integer conversions */
|
||||||
case T('d'):
|
case T('d'):
|
||||||
case T('i'): /* signed conversion */
|
case T('i'): /* signed conversion */
|
||||||
#if defined(NO_MERCY)
|
|
||||||
if (lm_flag & LF_LD) goto invalid_format;
|
|
||||||
#endif
|
|
||||||
base = 10;
|
base = 10;
|
||||||
sign = 1;
|
sign = 1;
|
||||||
goto handle_sign;
|
goto handle_sign;
|
||||||
@ -325,31 +336,19 @@ reswitch:
|
|||||||
|
|
||||||
/* unsigned integer conversions */
|
/* unsigned integer conversions */
|
||||||
case T('o'):
|
case T('o'):
|
||||||
#if defined(NO_MERCY)
|
|
||||||
if (lm_flag & LF_LD) goto invalid_format;
|
|
||||||
#endif
|
|
||||||
base = 8;
|
base = 8;
|
||||||
goto handle_nosign;
|
goto handle_nosign;
|
||||||
case T('u'):
|
case T('u'):
|
||||||
#if defined(NO_MERCY)
|
|
||||||
if (lm_flag & LF_LD) goto invalid_format;
|
|
||||||
#endif
|
|
||||||
base = 10;
|
base = 10;
|
||||||
goto handle_nosign;
|
goto handle_nosign;
|
||||||
case T('X'):
|
case T('X'):
|
||||||
upper = 1;
|
upper = 1;
|
||||||
case T('x'):
|
case T('x'):
|
||||||
#if defined(NO_MERCY)
|
|
||||||
if (lm_flag & LF_LD) goto invalid_format;
|
|
||||||
#endif
|
|
||||||
base = 16;
|
base = 16;
|
||||||
goto handle_nosign;
|
goto handle_nosign;
|
||||||
/* end of unsigned integer conversions */
|
/* end of unsigned integer conversions */
|
||||||
|
|
||||||
case T('p'): /* pointer */
|
case T('p'): /* pointer */
|
||||||
#if defined(NO_MERCY)
|
|
||||||
if (lm_flag & LF_LD) goto invalid_format;
|
|
||||||
#endif
|
|
||||||
base = 16;
|
base = 16;
|
||||||
|
|
||||||
if (width == 0) flagc |= FLAGC_SHARP;
|
if (width == 0) flagc |= FLAGC_SHARP;
|
||||||
@ -470,37 +469,89 @@ reswitch:
|
|||||||
case T('A'):
|
case T('A'):
|
||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
qse_mchar_t tmpbuf[100];
|
/* let me rely on snprintf until i implement
|
||||||
qse_mchar_t* tmpbufp;
|
* float-point to string conversion */
|
||||||
|
|
||||||
const char_t* xx;
|
|
||||||
const qse_mchar_t* yy;
|
|
||||||
int q;
|
int q;
|
||||||
|
qse_size_t fmtlen;
|
||||||
|
qse_fltmax_t v_fltmax;
|
||||||
|
long double v_ld;
|
||||||
|
double v_d;
|
||||||
|
|
||||||
#if defined(NO_MERCY)
|
if (lm_flag & LF_J)
|
||||||
if (lm_flag & ~LF_LD) goto invalid_format;
|
v_fltmax = va_arg (ap, qse_fltmax_t);
|
||||||
#endif
|
else if (lm_flag & (LF_LD | LF_L | LF_Q | LF_Z))
|
||||||
|
v_ld = va_arg (ap, long double);
|
||||||
if (fmt - percent < QSE_COUNTOF(fltfmt))
|
|
||||||
{
|
|
||||||
fltfmtp = fltfmt;
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
|
v_d = va_arg (ap, double);
|
||||||
|
|
||||||
|
fmtlen = fmt - percent;
|
||||||
|
if (fmtlen > fltfmt.capa)
|
||||||
{
|
{
|
||||||
fltfmtp = QSE_MMGR_ALLOC (QSE_MMGR_GETDFL(), QSE_SIZEOF(*fltfmtp) * (fmt - percent + 1));
|
if (fltfmt.ptr == fltfmt.sbuf)
|
||||||
if (fltfmtp == QSE_NULL) goto oops;
|
{
|
||||||
|
fltfmt.ptr = QSE_MMGR_ALLOC (QSE_MMGR_GETDFL(), QSE_SIZEOF(*fltfmt.ptr) * (fmtlen + 1));
|
||||||
|
if (fltfmt.ptr == QSE_NULL) goto oops;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
qse_mchar_t* tmpptr;
|
||||||
|
|
||||||
|
tmpptr = QSE_MMGR_REALLOC (QSE_MMGR_GETDFL(), fltfmt.ptr, QSE_SIZEOF(*fltfmt.ptr) * (fmtlen + 1));
|
||||||
|
if (tmpptr == QSE_NULL) goto oops;
|
||||||
|
fltfmt.ptr = tmpptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
fltfmt.capa = fmtlen;
|
||||||
}
|
}
|
||||||
for (xx = percent, q = 0; xx < fmt; xx++) fltfmtp[q++] = *xx;
|
|
||||||
fltfmtp[q] = QSE_MT('\0');
|
|
||||||
|
|
||||||
if (lm_flag & LF_LD)
|
fltfmt.ptr[fmtlen] = QSE_MT('\0');
|
||||||
snprintf (tmpbuf, QSE_SIZEOF(tmpbuf), fltfmtp, va_arg (ap, long double));
|
while (fmtlen > 0)
|
||||||
else
|
{
|
||||||
snprintf (tmpbuf, QSE_SIZEOF(tmpbuf), fltfmtp, va_arg (ap, double));
|
fmtlen--;
|
||||||
|
fltfmt.ptr[fmtlen] = percent[fmtlen];
|
||||||
|
}
|
||||||
|
|
||||||
for (yy = tmpbuf, q = 0; *yy; ) fltbuf[q++] = *yy++;
|
while (1)
|
||||||
fltbuf[q] = QSE_T('\0');
|
{
|
||||||
sp = fltbuf;
|
qse_size_t newcapa;
|
||||||
|
|
||||||
|
if (lm_flag & LF_J)
|
||||||
|
q = snprintf ((qse_mchar_t*)fltout.ptr, fltout.capa + 1, fltfmt.ptr, v_fltmax);
|
||||||
|
else if (lm_flag & (LF_LD | LF_L | LF_Q | LF_Z))
|
||||||
|
q = snprintf ((qse_mchar_t*)fltout.ptr, fltout.capa + 1, fltfmt.ptr, v_ld);
|
||||||
|
else
|
||||||
|
q = snprintf ((qse_mchar_t*)fltout.ptr, fltout.capa + 1, fltfmt.ptr, v_d);
|
||||||
|
if (q <= -1) goto oops;
|
||||||
|
if (q <= fltout.capa) break;
|
||||||
|
|
||||||
|
newcapa = fltout.capa * 2;
|
||||||
|
if (fltout.ptr == fltout.sbuf)
|
||||||
|
{
|
||||||
|
fltout.ptr = QSE_MMGR_ALLOC (QSE_MMGR_GETDFL(), QSE_SIZEOF(char_t) * (newcapa + 1));
|
||||||
|
if (fltout.ptr == QSE_NULL) goto oops;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
char_t* tmpptr;
|
||||||
|
|
||||||
|
tmpptr = QSE_MMGR_REALLOC (QSE_MMGR_GETDFL(), fltout.ptr, QSE_SIZEOF(char_t) * (newcapa + 1));
|
||||||
|
if (tmpptr == QSE_NULL) goto oops;
|
||||||
|
fltout.ptr = tmpptr;
|
||||||
|
}
|
||||||
|
fltout.capa = newcapa;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (QSE_SIZEOF(char_t) != QSE_SIZEOF(qse_mchar_t))
|
||||||
|
{
|
||||||
|
fltout.ptr[q] = T('\0');
|
||||||
|
while (q > 0)
|
||||||
|
{
|
||||||
|
q--;
|
||||||
|
fltout.ptr[q] = ((qse_mchar_t*)fltout.ptr)[q];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sp = fltout.ptr;
|
||||||
flagc &= ~FLAGC_DOT;
|
flagc &= ~FLAGC_DOT;
|
||||||
width = 0;
|
width = 0;
|
||||||
precision = 0;
|
precision = 0;
|
||||||
@ -532,20 +583,16 @@ handle_nosign:
|
|||||||
num = va_arg (ap, qse_uintmax_t);
|
num = va_arg (ap, qse_uintmax_t);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
else if (lm_flag & LF_T)
|
||||||
|
num = va_arg (ap, qse_ptrdiff_t);
|
||||||
|
else if (lm_flag & LF_Z)
|
||||||
|
num = va_arg (ap, qse_size_t);
|
||||||
#if (QSE_SIZEOF_LONG_LONG > 0)
|
#if (QSE_SIZEOF_LONG_LONG > 0)
|
||||||
else if (lm_flag & LF_Q)
|
else if (lm_flag & LF_Q)
|
||||||
num = va_arg (ap, unsigned long long int);
|
num = va_arg (ap, unsigned long long int);
|
||||||
#endif
|
#endif
|
||||||
|
else if (lm_flag & (LF_L | LF_LD))
|
||||||
#if 0
|
|
||||||
else if (lm_flag & LF_T)
|
|
||||||
num = va_arg (ap, ptrdiff_t);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
else if (lm_flag & LF_L)
|
|
||||||
num = va_arg (ap, long int);
|
num = va_arg (ap, long int);
|
||||||
else if (lm_flag & LF_Z)
|
|
||||||
num = va_arg (ap, qse_size_t);
|
|
||||||
else if (lm_flag & LF_H)
|
else if (lm_flag & LF_H)
|
||||||
num = (unsigned short int)va_arg (ap, int);
|
num = (unsigned short int)va_arg (ap, int);
|
||||||
else if (lm_flag & LF_C)
|
else if (lm_flag & LF_C)
|
||||||
@ -579,19 +626,16 @@ handle_sign:
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
else if (lm_flag & LF_T)
|
||||||
|
num = va_arg(ap, qse_ptrdiff_t);
|
||||||
|
else if (lm_flag & LF_Z)
|
||||||
|
num = va_arg (ap, qse_ssize_t);
|
||||||
#if (QSE_SIZEOF_LONG_LONG > 0)
|
#if (QSE_SIZEOF_LONG_LONG > 0)
|
||||||
else if (lm_flag & LF_Q)
|
else if (lm_flag & LF_Q)
|
||||||
num = va_arg (ap, long long int);
|
num = va_arg (ap, long long int);
|
||||||
#endif
|
#endif
|
||||||
|
else if (lm_flag & (LF_L | LF_LD))
|
||||||
#if 0
|
|
||||||
else if (lm_flag & LF_T)
|
|
||||||
num = va_arg(ap, ptrdiff_t);
|
|
||||||
#endif
|
|
||||||
else if (lm_flag & LF_L)
|
|
||||||
num = va_arg (ap, long int);
|
num = va_arg (ap, long int);
|
||||||
else if (lm_flag & LF_Z)
|
|
||||||
num = va_arg (ap, qse_ssize_t);
|
|
||||||
else if (lm_flag & LF_H)
|
else if (lm_flag & LF_H)
|
||||||
num = (short int)va_arg (ap, int);
|
num = (short int)va_arg (ap, int);
|
||||||
else if (lm_flag & LF_C)
|
else if (lm_flag & LF_C)
|
||||||
@ -684,11 +728,18 @@ invalid_format:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
done:
|
||||||
|
if (fltfmt.ptr != fltfmt.sbuf)
|
||||||
|
QSE_MMGR_FREE (QSE_MMGR_GETDFL(), fltfmt.ptr);
|
||||||
|
if (fltout.ptr != fltout.sbuf)
|
||||||
|
QSE_MMGR_FREE (QSE_MMGR_GETDFL(), fltout.ptr);
|
||||||
|
return outcnt;
|
||||||
|
|
||||||
oops:
|
oops:
|
||||||
if (fltfmtp && fltfmtp != fltfmt)
|
if (fltfmt.ptr != fltfmt.sbuf)
|
||||||
{
|
QSE_MMGR_FREE (QSE_MMGR_GETDFL(), fltfmt.ptr);
|
||||||
QSE_MMGR_FREE (QSE_MMGR_GETDFL(), fltfmtp);
|
if (fltout.ptr != fltout.sbuf)
|
||||||
}
|
QSE_MMGR_FREE (QSE_MMGR_GETDFL(), fltout.ptr);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
#undef PUT_CHAR
|
#undef PUT_CHAR
|
||||||
|
Loading…
x
Reference in New Issue
Block a user