added prefix to qse_fmtintmax() and qse_fmtuintmax().

chnaged awk's printf to use qse_fmtintmax().
This commit is contained in:
hyung-hwan 2011-11-07 00:01:19 +00:00
parent 226795c03e
commit 10b0469ee1
6 changed files with 388 additions and 395 deletions

View File

@ -29,72 +29,50 @@
*/
/**
* The qse_fmtintmaxtombs_flag_t type defines enumerators to change the
* behavior of qse_fmtintmaxtombs() and qse_fmtuintmaxtombs().
* The qse_fmtintmax_flag_t type defines enumerators to change the
* behavior of qse_fmtintmax() and qse_fmtuintmax().
*/
enum qse_fmtintmaxtombs_flag_t
enum qse_fmtintmax_flag_t
{
/** Don't truncate if the buffer is not large enough */
QSE_FMTINTMAXTOMBS_NOTRUNC = (0x100 << 0),
QSE_FMTINTMAX_NOTRUNC = (0x100 << 0),
/** Don't append a terminating null */
QSE_FMTINTMAXTOMBS_NONULL = (0x100 << 1),
QSE_FMTINTMAX_NONULL = (0x100 << 1),
/** Use uppercase letters for alphabetic digits */
QSE_FMTINTMAXTOMBS_UPPERCASE = (0x100 << 2),
QSE_FMTINTMAX_UPPERCASE = (0x100 << 2),
/** Insert a plus sign for a positive integer including 0 */
QSE_FMTINTMAXTOMBS_PLUSSIGN = (0x100 << 3),
QSE_FMTINTMAX_PLUSSIGN = (0x100 << 3),
/** Insert a space for a positive integer including 0 */
QSE_FMTINTMAX_EMPTYSIGN = (0x100 << 4),
/** Fill the right part of the string */
QSE_FMTINTMAXTOMBS_FILLRIGHT = (0x100 << 4),
QSE_FMTINTMAX_FILLRIGHT = (0x100 << 5),
/** Fill between the sign chacter and the digit part */
QSE_FMTINTMAXTOMBS_FILLCENTER = (0x100 << 5)
QSE_FMTINTMAX_FILLCENTER = (0x100 << 6)
};
#define QSE_FMTINTMAXTOMBS_NOTRUNC QSE_FMTINTMAXTOMBS_NOTRUNC
#define QSE_FMTINTMAXTOMBS_NONULL QSE_FMTINTMAXTOMBS_NONULL
#define QSE_FMTINTMAXTOMBS_UPPERCASE QSE_FMTINTMAXTOMBS_UPPERCASE
#define QSE_FMTINTMAXTOMBS_PLUSSIGN QSE_FMTINTMAXTOMBS_PLUSSIGN
#define QSE_FMTINTMAXTOMBS_FILLRIGHT QSE_FMTINTMAXTOMBS_FILLRIGHT
#define QSE_FMTINTMAXTOMBS_FILLCENTER QSE_FMTINTMAXTOMBS_FILLCENTER
/**
* The qse_fmtintmaxtowcs_flag_t type defines enumerators to change the
* behavior of qse_fmtintmaxtowcs() and qse_fmtuintmaxtowcs().
*/
enum qse_fmtintmaxtowcs_flag_t
{
/** Don't truncate if the buffer is not large enough */
QSE_FMTINTMAXTOWCS_NOTRUNC = (0x100 << 0),
/** Don't append a terminating null */
QSE_FMTINTMAXTOWCS_NONULL = (0x100 << 1),
/** Use uppercase letters for alphabetic digits */
QSE_FMTINTMAXTOWCS_UPPERCASE = (0x100 << 2),
/** Insert a plus sign for a positive integer including 0 */
QSE_FMTINTMAXTOWCS_PLUSSIGN = (0x100 << 3),
/** Fill the right part of the string */
QSE_FMTINTMAXTOWCS_FILLRIGHT = (0x100 << 4),
/** Fill between the sign chacter and the digit part */
QSE_FMTINTMAXTOWCS_FILLCENTER = (0x100 << 5)
};
#define QSE_FMTINTMAXTOWCS_NOTRUNC QSE_FMTINTMAXTOWCS_NOTRUNC
#define QSE_FMTINTMAXTOWCS_NONULL QSE_FMTINTMAXTOWCS_NONULL
#define QSE_FMTINTMAXTOWCS_UPPERCASE QSE_FMTINTMAXTOWCS_UPPERCASE
#define QSE_FMTINTMAXTOWCS_PLUSSIGN QSE_FMTINTMAXTOWCS_PLUSSIGN
#define QSE_FMTINTMAXTOWCS_FILLRIGHT QSE_FMTINTMAXTOWCS_FILLRIGHT
#define QSE_FMTINTMAXTOWCS_FILLCENTER QSE_FMTINTMAXTOWCS_FILLCENTER
#define QSE_FMTINTMAX_NOTRUNC QSE_FMTINTMAX_NOTRUNC
#define QSE_FMTINTMAX_NONULL QSE_FMTINTMAX_NONULL
#define QSE_FMTINTMAX_UPPERCASE QSE_FMTINTMAX_UPPERCASE
#define QSE_FMTINTMAX_PLUSSIGN QSE_FMTINTMAX_PLUSSIGN
#define QSE_FMTINTMAX_EMPTYSIGN QSE_FMTINTMAX_EMPTYSIGN
#define QSE_FMTINTMAX_FILLRIGHT QSE_FMTINTMAX_FILLRIGHT
#define QSE_FMTINTMAX_FILLCENTER QSE_FMTINTMAX_FILLCENTER
#ifdef QSE_CHAR_IS_MCHAR
# define QSE_FMTINTMAX_NOTRUNC QSE_FMTINTMAXTOMBS_NOTRUNC
# define QSE_FMTINTMAX_NONULL QSE_FMTINTMAXTOMBS_NONULL
# define QSE_FMTINTMAX_UPPERCASE QSE_FMTINTMAXTOMBS_UPPERCASE
# define QSE_FMTINTMAX_PLUSSIGN QSE_FMTINTMAXTOMBS_PLUSSIGN
# define QSE_FMTINTMAX_FILLRIGHT QSE_FMTINTMAXTOMBS_FILLRIGHT
# define QSE_FMTINTMAX_FILLCENTER QSE_FMTINTMAXTOMBS_FILLCENTER
#else
# define QSE_FMTINTMAX_NOTRUNC QSE_FMTINTMAXTOWCS_NOTRUNC
# define QSE_FMTINTMAX_NONULL QSE_FMTINTMAXTOWCS_NONULL
# define QSE_FMTINTMAX_UPPERCASE QSE_FMTINTMAXTOWCS_UPPERCASE
# define QSE_FMTINTMAX_PLUSSIGN QSE_FMTINTMAXTOWCS_PLUSSIGN
# define QSE_FMTINTMAX_FILLRIGHT QSE_FMTINTMAXTOWCS_FILLRIGHT
# define QSE_FMTINTMAX_FILLCENTER QSE_FMTINTMAXTOWCS_FILLCENTER
#endif
#define QSE_FMTINTMAXTOMBS_NOTRUNC QSE_FMTINTMAX_NOTRUNC
#define QSE_FMTINTMAXTOMBS_NONULL QSE_FMTINTMAX_NONULL
#define QSE_FMTINTMAXTOMBS_UPPERCASE QSE_FMTINTMAX_UPPERCASE
#define QSE_FMTINTMAXTOMBS_PLUSSIGN QSE_FMTINTMAX_PLUSSIGN
#define QSE_FMTINTMAXTOMBS_EMPTYSIGN QSE_FMTINTMAX_EMPTYSIGN
#define QSE_FMTINTMAXTOMBS_FILLRIGHT QSE_FMTINTMAX_FILLRIGHT
#define QSE_FMTINTMAXTOMBS_FILLCENTER QSE_FMTINTMAX_FILLCENTER
#define QSE_FMTINTMAXTOWCS_NOTRUNC QSE_FMTINTMAX_NOTRUNC
#define QSE_FMTINTMAXTOWCS_NONULL QSE_FMTINTMAX_NONULL
#define QSE_FMTINTMAXTOWCS_UPPERCASE QSE_FMTINTMAX_UPPERCASE
#define QSE_FMTINTMAXTOWCS_PLUSSIGN QSE_FMTINTMAX_PLUSSIGN
#define QSE_FMTINTMAXTOWCS_EMPTYSIGN QSE_FMTINTMAX_EMPTYSIGN
#define QSE_FMTINTMAXTOWCS_FILLRIGHT QSE_FMTINTMAX_FILLRIGHT
#define QSE_FMTINTMAXTOWCS_FILLCENTER QSE_FMTINTMAX_FILLCENTER
#ifdef __cplusplus
extern "C" {
@ -124,8 +102,11 @@ extern "C" {
* The #QSE_FMTINTMAXTOMBS_UPPERCASE flag indicates that the function should
* use the uppercase letter for a alphabetic digit;
* You can set #QSE_FMTINTMAXTOMBS_NOTRUNC if you require lossless formatting.
* The #QSE_FMTINTMAXTOMBS_PLUSSIGN flag ensures that the plug sign is added
* for a positive integer including 0.
* The #QSE_FMTINTMAXTOMBS_PLUSSIGN flag and #QSE_FMTINTMAXTOMBS_EMPTYSIGN
* ensures that the plus sign and a space is added for a positive integer
* including 0 respectively.
*
* If @a prefix is not #QSE_NULL, it is inserted before the digits.
*
* @return
* - -1 if the base is not between 2 and 36 inclusive.
@ -141,7 +122,8 @@ int qse_fmtintmaxtombs (
int bufsize, /**< buffer size */
qse_intmax_t value, /**< integer to format */
int base_and_flags, /**< base ORed with flags */
qse_mchar_t fillchar /**< fill character */
qse_mchar_t fillchar, /**< fill character */
const qse_mchar_t* prefix /**< prefix */
);
/**
@ -168,8 +150,11 @@ int qse_fmtintmaxtombs (
* The #QSE_FMTINTMAXTOWCS_UPPERCASE flag indicates that the function should
* use the uppercase letter for a alphabetic digit;
* You can set #QSE_FMTINTMAXTOWCS_NOTRUNC if you require lossless formatting.
* The #QSE_FMTINTMAXTOWCS_PLUSSIGN flag ensures that the plug sign is added
* for a positive integer including 0.
* The #QSE_FMTINTMAXTOWCS_PLUSSIGN flag and #QSE_FMTINTMAXTOWCS_EMPTYSIGN
* ensures that the plus sign and a space is added for a positive integer
* including 0 respectively.
*
* If @a prefix is not #QSE_NULL, it is inserted before the digits.
*
* @return
* - -1 if the base is not between 2 and 36 inclusive.
@ -185,7 +170,8 @@ int qse_fmtintmaxtowcs (
int bufsize, /**< buffer size */
qse_intmax_t value, /**< integer to format */
int base_and_flags, /**< base ORed with flags */
qse_wchar_t fillchar /**< fill character */
qse_wchar_t fillchar, /**< fill character */
const qse_wchar_t* prefix /**< prefix */
);
/** @def qse_fmtintmax
@ -193,9 +179,9 @@ int qse_fmtintmaxtowcs (
* #QSE_CHAR_IS_MCHAR, and qse_fmtintmaxtowcs() if #QSE_CHAR_IS_WCHAR.
*/
#ifdef QSE_CHAR_IS_MCHAR
# define qse_fmtintmax(b,sz,v,bf,fc) qse_fmtintmaxtombs(b,sz,v,bf,fc)
# define qse_fmtintmax(b,sz,v,bf,fc,pf) qse_fmtintmaxtombs(b,sz,v,bf,fc,pf)
#else
# define qse_fmtintmax(b,sz,v,bf,fc) qse_fmtintmaxtowcs(b,sz,v,bf,fc)
# define qse_fmtintmax(b,sz,v,bf,fc,pf) qse_fmtintmaxtowcs(b,sz,v,bf,fc,pf)
#endif
/**
@ -208,7 +194,8 @@ int qse_fmtuintmaxtombs (
int bufsize, /**< buffer size */
qse_uintmax_t value, /**< integer to format */
int base_and_flags, /**< base ORed with flags */
qse_mchar_t fillchar /**< fill character */
qse_mchar_t fillchar, /**< fill character */
const qse_mchar_t* prefix /**< prefix */
);
/**
@ -221,7 +208,8 @@ int qse_fmtuintmaxtowcs (
int bufsize, /**< buffer size */
qse_uintmax_t value, /**< integer to format */
int base_and_flags, /**< base ORed with flags */
qse_wchar_t fillchar /**< fill character */
qse_wchar_t fillchar, /**< fill character */
const qse_wchar_t* prefix /**< prefix */
);
/** @def qse_fmtuintmax
@ -229,9 +217,9 @@ int qse_fmtuintmaxtowcs (
* #QSE_CHAR_IS_MCHAR, and qse_fmtuintmaxtowcs() if #QSE_CHAR_IS_WCHAR.
*/
#ifdef QSE_CHAR_IS_MCHAR
# define qse_fmtuintmax(b,sz,v,bf,fc) qse_fmtuintmaxtombs(b,sz,v,bf,fc)
# define qse_fmtuintmax(b,sz,v,bf,fc,pf) qse_fmtuintmaxtombs(b,sz,v,bf,fc,pf)
#else
# define qse_fmtuintmax(b,sz,v,bf,fc) qse_fmtuintmaxtowcs(b,sz,v,bf,fc)
# define qse_fmtuintmax(b,sz,v,bf,fc,pf) qse_fmtuintmaxtowcs(b,sz,v,bf,fc,pf)
#endif
#ifdef __cplusplus

View File

@ -6662,7 +6662,7 @@ qse_char_t* qse_awk_rtx_format (
const qse_char_t* fmt, qse_size_t fmt_len,
qse_size_t nargs_on_stack, qse_awk_nde_t* args, qse_size_t* len)
{
qse_size_t i, j;
qse_size_t i;
qse_size_t stack_arg_idx = 1;
qse_awk_val_t* val;
@ -6674,6 +6674,14 @@ qse_char_t* qse_awk_rtx_format (
} \
)
#define OUT_STR(ptr,len) QSE_BLOCK( \
if (qse_str_ncat (out, (ptr), (len)) == -1) \
{ \
SETERR_COD (rtx, QSE_AWK_ENOMEM); \
return QSE_NULL; \
} \
)
#define FMT_CHAR(c) QSE_BLOCK( \
if (qse_str_ccat (fbu, (c)) == -1) \
{ \
@ -6682,8 +6690,16 @@ qse_char_t* qse_awk_rtx_format (
} \
)
#define FMT_STR(ptr,len) QSE_BLOCK( \
if (qse_str_ncat (fbu, (ptr), (len)) == -1) \
{ \
SETERR_COD (rtx, QSE_AWK_ENOMEM); \
return QSE_NULL; \
} \
)
#define GROW(buf) QSE_BLOCK( \
if ((buf)->ptr != QSE_NULL) \
if ((buf)->ptr) \
{ \
QSE_AWK_FREE (rtx->awk, (buf)->ptr); \
(buf)->ptr = QSE_NULL; \
@ -6695,6 +6711,24 @@ qse_char_t* qse_awk_rtx_format (
{ \
SETERR_COD (rtx, QSE_AWK_ENOMEM); \
(buf)->len = 0; \
return QSE_NULL; \
} \
)
#define GROW_WITH_INC(buf,incv) QSE_BLOCK( \
if ((buf)->ptr) \
{ \
QSE_AWK_FREE (rtx->awk, (buf)->ptr); \
(buf)->ptr = QSE_NULL; \
} \
(buf)->len += ((incv) > (buf)->inc)? (incv): (buf)->inc; \
(buf)->ptr = (qse_char_t*)QSE_AWK_ALLOC ( \
rtx->awk, (buf)->len * QSE_SIZEOF(qse_char_t)); \
if ((buf)->ptr == QSE_NULL) \
{ \
SETERR_COD (rtx, QSE_AWK_ENOMEM); \
(buf)->len = 0; \
return QSE_NULL; \
} \
)
@ -6719,16 +6753,36 @@ qse_char_t* qse_awk_rtx_format (
for (i = 0; i < fmt_len; i++)
{
qse_long_t width = -1, prec = -1;
int minus = 0;
qse_long_t wp[2];
int wp_idx;
#define WP_WIDTH 0
#define WP_PRECISION 1
int flags;
#define FLAG_SPACE (1 << 0)
#define FLAG_HASH (1 << 1)
#define FLAG_ZERO (1 << 2)
#define FLAG_PLUS (1 << 3)
#define FLAG_MINUS (1 << 4)
if (QSE_STR_LEN(fbu) == 0)
{
if (fmt[i] == QSE_T('%')) FMT_CHAR (fmt[i]);
else OUT_CHAR (fmt[i]);
/* format specifier is empty */
if (fmt[i] == QSE_T('%'))
{
/* add % to format specifier (fbu) */
FMT_CHAR (fmt[i]);
}
else
{
/* normal output */
OUT_CHAR (fmt[i]);
}
continue;
}
/* handle flags */
#if 0
while (i < fmt_len &&
(fmt[i] == QSE_T(' ') || fmt[i] == QSE_T('#') ||
fmt[i] == QSE_T('0') || fmt[i] == QSE_T('+') ||
@ -6737,11 +6791,47 @@ qse_char_t* qse_awk_rtx_format (
if (fmt[i] == QSE_T('-')) minus = 1;
FMT_CHAR (fmt[i]); i++;
}
#endif
flags = 0;
while (i < fmt_len)
{
switch (fmt[i])
{
case QSE_T(' '):
flags |= FLAG_SPACE;
break;
case QSE_T('#'):
flags |= FLAG_HASH;
break;
case QSE_T('0'):
flags |= FLAG_ZERO;
break;
case QSE_T('+'):
flags |= FLAG_PLUS;
break;
case QSE_T('-'):
flags |= FLAG_MINUS;
break;
default:
goto wp_mod_init;
}
FMT_CHAR (fmt[i]); i++;
}
wp_mod_init:
wp[WP_WIDTH] = -1; /* width */
wp[WP_PRECISION] = -1; /* precision */
wp_idx = WP_WIDTH; /* width first */
wp_mod_main:
if (i < fmt_len && fmt[i] == QSE_T('*'))
{
/* variable width/precision modifier.
* take the width/precision from a parameter and
* transform it to a fixed length format */
qse_awk_val_t* v;
qse_char_t* p;
int n;
if (args == QSE_NULL)
@ -6772,7 +6862,7 @@ qse_char_t* qse_awk_rtx_format (
}
qse_awk_rtx_refupval (rtx, v);
n = qse_awk_rtx_valtolong (rtx, v, &width);
n = qse_awk_rtx_valtolong (rtx, v, &wp[wp_idx]);
qse_awk_rtx_refdownval (rtx, v);
if (n <= -1) return QSE_NULL;
@ -6781,23 +6871,16 @@ qse_char_t* qse_awk_rtx_format (
n = qse_fmtintmax (
rtx->format.tmp.ptr,
rtx->format.tmp.len,
width,
10 | QSE_FMTINTMAX_NOTRUNC,
QSE_T('\0')
wp[wp_idx],
10 | QSE_FMTINTMAX_NOTRUNC | QSE_FMTINTMAX_NONULL,
QSE_T('\0'),
QSE_NULL
);
if (n <= -1)
{
/* TODO: utilize n in GROW.
* since -n is the number of characters required
* including terminating null, it can be used there
* this doesn't have to be in the loop any more */
GROW (&rtx->format.tmp);
if (rtx->format.tmp.ptr == QSE_NULL)
{
SETERR_COD (rtx, QSE_AWK_ENOMEM);
return QSE_NULL;
}
/* -n is the number of characters required
* including terminating null */
GROW_WITH_INC (&rtx->format.tmp, -n);
continue;
}
@ -6805,14 +6888,7 @@ qse_char_t* qse_awk_rtx_format (
}
while (1);
/* TODO: we know that n is the length.
* the contents can be added without scanning the whole string again */
p = rtx->format.tmp.ptr;
while (*p != QSE_T('\0'))
{
FMT_CHAR (*p);
p++;
}
FMT_STR(rtx->format.tmp.ptr, n);
if (args == QSE_NULL || val != QSE_NULL) stack_arg_idx++;
else args = args->next;
@ -6820,115 +6896,26 @@ qse_char_t* qse_awk_rtx_format (
}
else
{
/* fixed width/precision modifier */
if (i < fmt_len && QSE_AWK_ISDIGIT(rtx->awk, fmt[i]))
{
width = 0;
wp[wp_idx] = 0;
do
{
width = width * 10 + fmt[i] - QSE_T('0');
wp[wp_idx] = wp[wp_idx] * 10 + fmt[i] - QSE_T('0');
FMT_CHAR (fmt[i]); i++;
}
while (i < fmt_len && QSE_AWK_ISDIGIT(rtx->awk, fmt[i]));
}
}
if (i < fmt_len && fmt[i] == QSE_T('.'))
if (wp_idx == WP_WIDTH && i < fmt_len && fmt[i] == QSE_T('.'))
{
prec = 0;
wp[WP_PRECISION] = 0;
FMT_CHAR (fmt[i]); i++;
}
if (i < fmt_len && fmt[i] == QSE_T('*'))
{
qse_awk_val_t* v;
qse_char_t* p;
int n;
if (args == QSE_NULL)
{
if (stack_arg_idx >= nargs_on_stack)
{
SETERR_COD (rtx, QSE_AWK_EFMTARG);
return QSE_NULL;
}
v = qse_awk_rtx_getarg (rtx, stack_arg_idx);
}
else
{
if (val != QSE_NULL)
{
if (stack_arg_idx >= nargs_on_stack)
{
SETERR_COD (rtx, QSE_AWK_EFMTARG);
return QSE_NULL;
}
v = val;
}
else
{
v = eval_expression (rtx, args);
if (v == QSE_NULL) return QSE_NULL;
}
}
qse_awk_rtx_refupval (rtx, v);
n = qse_awk_rtx_valtolong (rtx, v, &prec);
qse_awk_rtx_refdownval (rtx, v);
if (n <= -1) return QSE_NULL;
do
{
n = qse_fmtintmax (
rtx->format.tmp.ptr,
rtx->format.tmp.len,
prec,
10 | QSE_FMTINTMAX_NOTRUNC,
QSE_T('\0')
);
if (n <= -1)
{
/* TODO: utilize n in GROW.
* since -n is the number of characters required
* including terminating null, it can be used there.
* this doesn't have to be in the loop any more */
GROW (&rtx->format.tmp);
if (rtx->format.tmp.ptr == QSE_NULL)
{
SETERR_COD (rtx, QSE_AWK_ENOMEM);
return QSE_NULL;
}
continue;
}
break;
}
while (1);
/* TODO: we know that n is the length.
* the contents can be added without scanning the whole string again */
p = rtx->format.tmp.ptr;
while (*p != QSE_T('\0'))
{
FMT_CHAR (*p);
p++;
}
if (args == QSE_NULL || val != QSE_NULL) stack_arg_idx++;
else args = args->next;
i++;
}
else
{
if (i < fmt_len && QSE_AWK_ISDIGIT(rtx->awk, fmt[i]))
{
prec = 0;
do
{
prec = prec * 10 + fmt[i] - QSE_T('0');
FMT_CHAR (fmt[i]); i++;
}
while (i < fmt_len && QSE_AWK_ISDIGIT(rtx->awk, fmt[i]));
}
wp_idx = WP_PRECISION; /* change index to precision */
goto wp_mod_main;
}
if (i >= fmt_len) break;
@ -6939,27 +6926,8 @@ qse_char_t* qse_awk_rtx_format (
{
qse_awk_val_t* v;
qse_long_t l;
qse_char_t* p;
int n;
#if QSE_SIZEOF_LONG_LONG > 0
FMT_CHAR (QSE_T('l'));
FMT_CHAR (QSE_T('l'));
FMT_CHAR (fmt[i]);
#elif QSE_SIZEOF___INT64 > 0
FMT_CHAR (QSE_T('I'));
FMT_CHAR (QSE_T('6'));
FMT_CHAR (QSE_T('4'));
FMT_CHAR (fmt[i]);
#elif QSE_SIZEOF_LONG > 0
FMT_CHAR (QSE_T('l'));
FMT_CHAR (fmt[i]);
#elif QSE_SIZEOF_INT > 0
FMT_CHAR (fmt[i]);
#else
#error unsupported integer size
#endif
if (args == QSE_NULL)
{
if (stack_arg_idx >= nargs_on_stack)
@ -6992,6 +6960,110 @@ qse_char_t* qse_awk_rtx_format (
qse_awk_rtx_refdownval (rtx, v);
if (n <= -1) return QSE_NULL;
#if 0
/* TODO: finish this part... replace sprintf */
{
int fmt_flags;
int fmt_uint = 0;
qse_char_t fmt_fill = QSE_T('\0');
const qse_char_t* fmt_prefix = QSE_NULL;
if (l == 0 && wp[WP_PRECISION] == 0)
{
}
fmt_flags = QSE_FMTINTMAX_NOTRUNC | QSE_FMTINTMAX_NONULL;
if (flags & FLAG_ZERO)
{
fmt_fill = QSE_T('0');
}
else
{
if (!(flags & FLAG_MINUS)) fmt_flags |= QSE_FMTINTMAX_FILLCENTER;
}
switch (fmt[i])
{
case QSE_T('X'):
fmt_flags |= QSE_FMTINTMAX_UPPERCASE;
case QSE_T('x'):
fmt_flags |= 16;
fmt_uint = 1;
if (l && (flags & FLAG_HASH)) fmt_prefix = QSE_T("0x");
break;
case QSE_T('o'):
fmt_flags |= 8;
fmt_uint = 1;
if (l && (flags & FLAG_HASH)) fmt_prefix = QSE_T("0");
break;
default:
fmt_flags |= 10;
if (flags & FLAG_PLUS) fmt_flags |= QSE_FMTINTMAX_PLUSSIGN;
if (flags & FLAG_SPACE) fmt_flags |= QSE_FMTINTMAX_EMPTYSIGN;
break;
}
qse_printf (QSE_T("width=>%d precision=%d\n"), wp[0], wp[1]);
do
{
if (fmt_uint)
{
n = qse_fmtuintmax (
rtx->format.tmp.ptr,
rtx->format.tmp.len,
l,
fmt_flags,
fmt_fill,
fmt_prefix
);
}
else
{
n = qse_fmtintmax (
rtx->format.tmp.ptr,
rtx->format.tmp.len,
l,
fmt_flags,
fmt_fill,
fmt_prefix
);
}
if (n <= -1)
{
/* -n is the number of characters required
* including terminating null */
GROW_WITH_INC (&rtx->format.tmp, -n);
continue;
}
break;
}
while (1);
OUT_STR (rtx->format.tmp.ptr, n);
}
#endif
#if QSE_SIZEOF_LONG_LONG > 0
FMT_CHAR (QSE_T('l'));
FMT_CHAR (QSE_T('l'));
FMT_CHAR (fmt[i]);
#elif QSE_SIZEOF___INT64 > 0
FMT_CHAR (QSE_T('I'));
FMT_CHAR (QSE_T('6'));
FMT_CHAR (QSE_T('4'));
FMT_CHAR (fmt[i]);
#elif QSE_SIZEOF_LONG > 0
FMT_CHAR (QSE_T('l'));
FMT_CHAR (fmt[i]);
#elif QSE_SIZEOF_INT > 0
FMT_CHAR (fmt[i]);
#else
#error unsupported integer size
#endif
do
{
n = rtx->awk->prm.sprintf (
@ -7013,12 +7085,6 @@ qse_char_t* qse_awk_rtx_format (
if (n == -1)
{
GROW (&rtx->format.tmp);
if (rtx->format.tmp.ptr == QSE_NULL)
{
SETERR_COD (rtx, QSE_AWK_ENOMEM);
return QSE_NULL;
}
continue;
}
@ -7026,12 +7092,7 @@ qse_char_t* qse_awk_rtx_format (
}
while (1);
p = rtx->format.tmp.ptr;
while (*p != QSE_T('\0'))
{
OUT_CHAR (*p);
p++;
}
OUT_STR (rtx->format.tmp.ptr, n);
}
else if (fmt[i] == QSE_T('e') || fmt[i] == QSE_T('E') ||
fmt[i] == QSE_T('g') || fmt[i] == QSE_T('G') ||
@ -7039,7 +7100,6 @@ qse_char_t* qse_awk_rtx_format (
{
qse_awk_val_t* v;
qse_real_t r;
qse_char_t* p;
int n;
FMT_CHAR (QSE_T('L'));
@ -7094,12 +7154,6 @@ qse_char_t* qse_awk_rtx_format (
if (n == -1)
{
GROW (&rtx->format.tmp);
if (rtx->format.tmp.ptr == QSE_NULL)
{
SETERR_COD (rtx, QSE_AWK_ENOMEM);
return QSE_NULL;
}
continue;
}
@ -7107,12 +7161,7 @@ qse_char_t* qse_awk_rtx_format (
}
while (1);
p = rtx->format.tmp.ptr;
while (*p != QSE_T('\0'))
{
OUT_CHAR (*p);
p++;
}
OUT_STR (rtx->format.tmp.ptr, n);
}
else if (fmt[i] == QSE_T('c'))
{
@ -7180,16 +7229,17 @@ qse_char_t* qse_awk_rtx_format (
return QSE_NULL;
}
if (prec == -1 || prec == 0 || prec > (qse_long_t)ch_len)
if (wp[WP_PRECISION] == -1 || wp[WP_PRECISION] == 0 || wp[WP_PRECISION] > (qse_long_t)ch_len)
{
prec = (qse_long_t)ch_len;
wp[WP_PRECISION] = (qse_long_t)ch_len;
}
if (prec > width) width = prec;
if (wp[WP_PRECISION] > wp[WP_WIDTH]) wp[WP_WIDTH] = wp[WP_PRECISION];
if (!minus)
if (!(flags & FLAG_MINUS))
{
while (width > prec)
/* right align */
while (wp[WP_WIDTH] > wp[WP_PRECISION])
{
if (qse_str_ccat (out, QSE_T(' ')) == -1)
{
@ -7197,11 +7247,11 @@ qse_char_t* qse_awk_rtx_format (
SETERR_COD (rtx, QSE_AWK_ENOMEM);
return QSE_NULL;
}
width--;
wp[WP_WIDTH]--;
}
}
if (prec > 0)
if (wp[WP_PRECISION] > 0)
{
if (qse_str_ccat (out, ch) == -1)
{
@ -7211,9 +7261,10 @@ qse_char_t* qse_awk_rtx_format (
}
}
if (minus)
if (flags & FLAG_MINUS)
{
while (width > prec)
/* left align */
while (wp[WP_WIDTH] > wp[WP_PRECISION])
{
if (qse_str_ccat (out, QSE_T(' ')) == -1)
{
@ -7221,7 +7272,7 @@ qse_char_t* qse_awk_rtx_format (
SETERR_COD (rtx, QSE_AWK_ENOMEM);
return QSE_NULL;
}
width--;
wp[WP_WIDTH]--;
}
}
@ -7295,12 +7346,13 @@ qse_char_t* qse_awk_rtx_format (
str_free = str_ptr;
}
if (prec == -1 || prec > (qse_long_t)str_len) prec = (qse_long_t)str_len;
if (prec > width) width = prec;
if (wp[WP_PRECISION] == -1 || wp[WP_PRECISION] > (qse_long_t)str_len) wp[WP_PRECISION] = (qse_long_t)str_len;
if (wp[WP_PRECISION] > wp[WP_WIDTH]) wp[WP_WIDTH] = wp[WP_PRECISION];
if (!minus)
if (!(flags & FLAG_MINUS))
{
while (width > prec)
/* right align */
while (wp[WP_WIDTH] > wp[WP_PRECISION])
{
if (qse_str_ccat (out, QSE_T(' ')) == -1)
{
@ -7310,11 +7362,11 @@ qse_char_t* qse_awk_rtx_format (
SETERR_COD (rtx, QSE_AWK_ENOMEM);
return QSE_NULL;
}
width--;
wp[WP_WIDTH]--;
}
}
for (k = 0; k < prec; k++)
for (k = 0; k < wp[WP_PRECISION]; k++)
{
if (qse_str_ccat (out, str_ptr[k]) == -1)
{
@ -7328,9 +7380,10 @@ qse_char_t* qse_awk_rtx_format (
if (str_free != QSE_NULL) QSE_AWK_FREE (rtx->awk, str_free);
if (minus)
if (flags & FLAG_MINUS)
{
while (width > prec)
/* left align */
while (wp[WP_WIDTH] > wp[WP_PRECISION])
{
if (qse_str_ccat (out, QSE_T(' ')) == -1)
{
@ -7338,7 +7391,7 @@ qse_char_t* qse_awk_rtx_format (
SETERR_COD (rtx, QSE_AWK_ENOMEM);
return QSE_NULL;
}
width--;
wp[WP_WIDTH]--;
}
}
@ -7346,8 +7399,11 @@ qse_char_t* qse_awk_rtx_format (
}
else /*if (fmt[i] == QSE_T('%'))*/
{
OUT_STR (QSE_STR_PTR(fbu), QSE_STR_LEN(fbu));
#if 0
for (j = 0; j < QSE_STR_LEN(fbu); j++)
OUT_CHAR (QSE_STR_CHAR(fbu,j));
#endif
OUT_CHAR (fmt[i]);
}
@ -7357,8 +7413,7 @@ qse_char_t* qse_awk_rtx_format (
}
/* flush uncompleted formatting sequence */
for (j = 0; j < QSE_STR_LEN(fbu); j++)
OUT_CHAR (QSE_STR_CHAR(fbu,j));
OUT_STR (QSE_STR_PTR(fbu), QSE_STR_LEN(fbu));
*len = QSE_STR_LEN(out);
return QSE_STR_PTR(out);

View File

@ -285,7 +285,8 @@ static int print_expr (qse_awk_t* awk, qse_awk_nde_t* nde)
buf, QSE_COUNTOF(buf),
((qse_awk_nde_int_t*)nde)->val,
10,
QSE_T('\0')
QSE_T('\0'),
QSE_NULL
);
PUT_SRCSTR (awk, buf);
}

View File

@ -19,15 +19,16 @@
*/
#include <qse/cmn/fmt.h>
#include <qse/cmn/str.h>
/* ==================== multibyte ===================================== */
static int fmt_unsigned_to_mbs (
qse_mchar_t* buf, int size,
qse_uintmax_t value, int base_and_flags,
qse_mchar_t fillchar, qse_mchar_t signchar)
qse_mchar_t fillchar, qse_mchar_t signchar, const qse_mchar_t* prefix)
{
qse_mchar_t tmp[(QSE_SIZEOF(qse_uintmax_t) * 8)];
int reslen, base, xsize, reqlen;
int reslen, base, xsize, reqlen, pflen;
qse_mchar_t* p, * bp, * be;
qse_mchar_t xbasechar;
@ -50,6 +51,14 @@ static int fmt_unsigned_to_mbs (
/* reslen is the length of the resulting string without padding. */
reslen = (int)(p - tmp);
if (signchar) reslen++; /* increment reslen for the sign character */
if (prefix)
{
/* since the length can be truncated for different type sizes,
* don't pass in a very long prefix. */
pflen = (int)qse_mbslen(prefix);
reslen += pflen;
}
/* get the required buffer size for lossless formatting */
reqlen = (base_and_flags & QSE_FMTINTMAXTOMBS_NONULL)? reslen: (reslen + 1);
@ -67,12 +76,13 @@ static int fmt_unsigned_to_mbs (
/* fill space */
if (fillchar != QSE_MT('\0'))
{
if (base_and_flags & QSE_FMTINTMAXTOMBS_FILLRIGHT)
{
/* emit sign */
if (signchar && bp < be) *bp++ = signchar;
/* copy prefix if necessary */
if (prefix) while (*prefix && bp < be) *bp++ = *prefix++;
/* copy the numeric string to the destination buffer */
while (p > tmp && bp < be) *bp++ = *--p;
@ -95,6 +105,8 @@ static int fmt_unsigned_to_mbs (
xsize--;
}
/* copy prefix if necessary */
if (prefix) while (*prefix && bp < be) *bp++ = *prefix++;
/* copy the numeric string to the destination buffer */
while (p > tmp && bp < be) *bp++ = *--p;
}
@ -110,6 +122,8 @@ static int fmt_unsigned_to_mbs (
/* emit sign */
if (signchar && bp < be) *bp++ = signchar;
/* copy prefix if necessary */
if (prefix) while (*prefix && bp < be) *bp++ = *prefix++;
/* copy the numeric string to the destination buffer */
while (p > tmp && bp < be) *bp++ = *--p;
}
@ -119,6 +133,8 @@ static int fmt_unsigned_to_mbs (
/* emit sign */
if (signchar && bp < be) *bp++ = signchar;
/* copy prefix if necessary */
if (prefix) while (*prefix && bp < be) *bp++ = *prefix++;
/* copy the numeric string to the destination buffer */
while (p > tmp && bp < be) *bp++ = *--p;
}
@ -129,7 +145,8 @@ static int fmt_unsigned_to_mbs (
int qse_fmtintmaxtombs (
qse_mchar_t* buf, int size,
qse_intmax_t value, int base_and_flags, qse_mchar_t fillchar)
qse_intmax_t value, int base_and_flags,
qse_mchar_t fillchar, const qse_mchar_t* prefix)
{
qse_mchar_t signchar;
qse_uintmax_t absvalue;
@ -144,18 +161,24 @@ int qse_fmtintmaxtombs (
signchar = QSE_MT('+');
absvalue = value;
}
else if (base_and_flags & QSE_FMTINTMAXTOMBS_EMPTYSIGN)
{
signchar = QSE_MT(' ');
absvalue = value;
}
else
{
signchar = QSE_MT('\0');
absvalue = value;
}
return fmt_unsigned_to_mbs (buf, size, absvalue, base_and_flags, fillchar, signchar);
return fmt_unsigned_to_mbs (buf, size, absvalue, base_and_flags, fillchar, signchar, prefix);
}
int qse_fmtuintmaxtombs (
qse_mchar_t* buf, int size,
qse_uintmax_t value, int base_and_flags, qse_mchar_t fillchar)
qse_uintmax_t value, int base_and_flags,
qse_mchar_t fillchar, const qse_mchar_t* prefix)
{
qse_mchar_t signchar;
@ -164,25 +187,28 @@ int qse_fmtuintmaxtombs (
{
signchar = QSE_MT('+');
}
else if (base_and_flags & QSE_FMTINTMAXTOMBS_EMPTYSIGN)
{
signchar = QSE_MT(' ');
}
else
{
signchar = QSE_MT('\0');
}
return fmt_unsigned_to_mbs (buf, size, value, base_and_flags, fillchar, signchar);
return fmt_unsigned_to_mbs (buf, size, value, base_and_flags, fillchar, signchar, prefix);
}
/* ==================== wide-char ===================================== */
#if 0
static int fmt_unsigned_to_wcs (
qse_wchar_t* buf, int size,
qse_uintmax_t value, int base_and_flags,
qse_wchar_t fillchar, qse_wchar_t signchar)
qse_wchar_t fillchar, qse_wchar_t signchar, const qse_wchar_t* prefix)
{
qse_wchar_t tmp[(QSE_SIZEOF(qse_uintmax_t) * 8)];
int reslen, base;
int reslen, base, xsize, reqlen, pflen;
qse_wchar_t* p, * bp, * be;
qse_wchar_t xbasechar;
@ -205,111 +231,14 @@ static int fmt_unsigned_to_wcs (
/* reslen is the length of the resulting string without padding. */
reslen = (int)(p - tmp);
if (signchar) reslen++; /* increment reslen for the sign character */
if (size <= 0 ||
((base_and_flags & QSE_FMTINTMAXTOWCS_NOTRUNC) && size <= reslen))
if (prefix)
{
/* conversion without loss requires at least 'reslen + 1'. */
return -(reslen + 1);
/* since the length can be truncated for different type sizes,
* don't pass in a very long prefix. */
pflen = (int)qse_wcslen(prefix);
reslen += pflen;
}
bp = buf;
be = buf + size - 1;
/* fill space */
if (fillchar != QSE_WT('\0'))
{
if (base_and_flags & QSE_FMTINTMAXTOWCS_FILLRIGHT)
{
/* emit sign */
if (signchar && bp < be) *bp++ = signchar;
/* copy the numeric string to the destination buffer */
while (p > tmp && bp < be) *bp++ = *--p;
/* fill the right side */
while (size - 1 > reslen)
{
*bp++ = fillchar;
size--;
}
}
else if (base_and_flags & QSE_FMTINTMAXTOWCS_FILLCENTER)
{
/* emit sign */
if (signchar && bp < be) *bp++ = signchar;
/* fill the left side */
while (size - 1 > reslen)
{
*bp++ = fillchar;
size--;
}
/* copy the numeric string to the destination buffer */
while (p > tmp && bp < be) *bp++ = *--p;
}
else
{
/* fill the left side */
while (size - 1 > reslen)
{
*bp++ = fillchar;
size--;
}
/* emit sign */
if (signchar && bp < be) *bp++ = signchar;
/* copy the numeric string to the destination buffer */
while (p > tmp && bp < be) *bp++ = *--p;
}
}
else
{
/* emit sign */
if (signchar && bp < be) *bp++ = signchar;
/* copy the numeric string to the destination buffer */
while (p > tmp && bp < be) *bp++ = *--p;
}
*bp = QSE_WT('\0');
return bp - buf;
}
#endif
static int fmt_unsigned_to_wcs (
qse_wchar_t* buf, int size,
qse_uintmax_t value, int base_and_flags,
qse_wchar_t fillchar, qse_wchar_t signchar)
{
qse_wchar_t tmp[(QSE_SIZEOF(qse_uintmax_t) * 8)];
int reslen, base, xsize, reqlen;
qse_wchar_t* p, * bp, * be;
qse_wchar_t xbasechar;
base = base_and_flags & 0xFF;
if (base < 2 || base > 36) return -1;
xbasechar = (base_and_flags & QSE_FMTINTMAXTOWCS_UPPERCASE)? QSE_WT('A'): QSE_WT('a');
/* store the resulting numeric string into 'tmp' first */
p = tmp;
do
{
int digit = value % base;
if (digit < 10) *p++ = digit + QSE_WT('0');
else *p++ = digit + xbasechar - 10;
value /= base;
}
while (value > 0);
/* reslen is the length of the resulting string without padding. */
reslen = (int)(p - tmp);
if (signchar) reslen++; /* increment reslen for the sign character */
/* get the required buffer size for lossless formatting */
reqlen = (base_and_flags & QSE_FMTINTMAXTOWCS_NONULL)? reslen: (reslen + 1);
@ -326,12 +255,13 @@ static int fmt_unsigned_to_wcs (
/* fill space */
if (fillchar != QSE_WT('\0'))
{
if (base_and_flags & QSE_FMTINTMAXTOWCS_FILLRIGHT)
{
/* emit sign */
if (signchar && bp < be) *bp++ = signchar;
/* copy prefix if necessary */
if (prefix) while (*prefix && bp < be) *bp++ = *prefix++;
/* copy the numeric string to the destination buffer */
while (p > tmp && bp < be) *bp++ = *--p;
@ -354,6 +284,8 @@ static int fmt_unsigned_to_wcs (
xsize--;
}
/* copy prefix if necessary */
if (prefix) while (*prefix && bp < be) *bp++ = *prefix++;
/* copy the numeric string to the destination buffer */
while (p > tmp && bp < be) *bp++ = *--p;
}
@ -369,6 +301,8 @@ static int fmt_unsigned_to_wcs (
/* emit sign */
if (signchar && bp < be) *bp++ = signchar;
/* copy prefix if necessary */
if (prefix) while (*prefix && bp < be) *bp++ = *prefix++;
/* copy the numeric string to the destination buffer */
while (p > tmp && bp < be) *bp++ = *--p;
}
@ -378,6 +312,8 @@ static int fmt_unsigned_to_wcs (
/* emit sign */
if (signchar && bp < be) *bp++ = signchar;
/* copy prefix if necessary */
if (prefix) while (*prefix && bp < be) *bp++ = *prefix++;
/* copy the numeric string to the destination buffer */
while (p > tmp && bp < be) *bp++ = *--p;
}
@ -388,7 +324,8 @@ static int fmt_unsigned_to_wcs (
int qse_fmtintmaxtowcs (
qse_wchar_t* buf, int size,
qse_intmax_t value, int base_and_flags, qse_wchar_t fillchar)
qse_intmax_t value, int base_and_flags,
qse_wchar_t fillchar, const qse_wchar_t* prefix)
{
qse_wchar_t signchar;
qse_uintmax_t absvalue;
@ -403,18 +340,24 @@ int qse_fmtintmaxtowcs (
signchar = QSE_WT('+');
absvalue = value;
}
else if (base_and_flags & QSE_FMTINTMAXTOMBS_EMPTYSIGN)
{
signchar = QSE_WT(' ');
absvalue = value;
}
else
{
signchar = QSE_WT('\0');
absvalue = value;
}
return fmt_unsigned_to_wcs (buf, size, absvalue, base_and_flags, fillchar, signchar);
return fmt_unsigned_to_wcs (buf, size, absvalue, base_and_flags, fillchar, signchar, prefix);
}
int qse_fmtuintmaxtowcs (
qse_wchar_t* buf, int size,
qse_uintmax_t value, int base_and_flags, qse_wchar_t fillchar)
qse_uintmax_t value, int base_and_flags,
qse_wchar_t fillchar, const qse_wchar_t* prefix)
{
qse_wchar_t signchar;
@ -423,11 +366,15 @@ int qse_fmtuintmaxtowcs (
{
signchar = QSE_WT('+');
}
else if (base_and_flags & QSE_FMTINTMAXTOMBS_EMPTYSIGN)
{
signchar = QSE_WT(' ');
}
else
{
signchar = QSE_WT('\0');
}
return fmt_unsigned_to_wcs (buf, size, value, base_and_flags, fillchar, signchar);
return fmt_unsigned_to_wcs (buf, size, value, base_and_flags, fillchar, signchar, prefix);
}

View File

@ -3,8 +3,9 @@
static int test_main (int argc, qse_char_t* argv[], qse_char_t* envp[])
{
qse_char_t buf[17];
qse_char_t buf[19];
int bases[] = { 2, 8, 10, 16 };
qse_char_t* prefix[] = { QSE_T("0b"), QSE_T("0"), QSE_NULL, QSE_T("0x") };
int flags[] =
{
QSE_FMTINTMAX_NOTRUNC | 0,
@ -31,7 +32,7 @@ static int test_main (int argc, qse_char_t* argv[], qse_char_t* envp[])
{
for (j = 0; j < QSE_COUNTOF(flags); j++)
{
int n = qse_fmtuintmax (buf, QSE_COUNTOF(buf), num, bases[i] | flags[j], QSE_T('.'));
int n = qse_fmtuintmax (buf, QSE_COUNTOF(buf), num, bases[i] | flags[j], QSE_T('.'), prefix[i]);
if (n <= -1)
{
qse_printf (QSE_T("%8X => [%4d:%04X] ERROR[%d]\n"), num, bases[i], flags[j], n);

View File

@ -5,6 +5,7 @@ static int test_main (int argc, qse_char_t* argv[], qse_char_t* envp[])
{
qse_char_t buf[129];
int bases[] = { 2, 8, 10, 16 };
qse_char_t* prefix[] = { QSE_T("0b"), QSE_T("0"), QSE_NULL, QSE_T("0x") };
int flags[] =
{
QSE_FMTINTMAX_PLUSSIGN,
@ -26,7 +27,7 @@ static int test_main (int argc, qse_char_t* argv[], qse_char_t* envp[])
{
for (j = 0; j < QSE_COUNTOF(flags); j++)
{
int n = qse_fmtintmax (buf, QSE_COUNTOF(buf), nums[k], bases[i] | flags[j] | QSE_FMTINTMAX_NOTRUNC, QSE_T('.'));
int n = qse_fmtintmax (buf, QSE_COUNTOF(buf), nums[k], bases[i] | flags[j] | QSE_FMTINTMAX_NOTRUNC, QSE_T('.'), prefix[i]);
if (n <= -1)
{
qse_printf (QSE_T("%8d => [%4d:%04X] ERROR[%d]\n"), (int)nums[k], bases[i], flags[j], n);