renamed moo_sprintfmtfromstack() to moo_strfmtcallstack().
refactored related functions
This commit is contained in:
parent
3f274d74b7
commit
054313b96c
@ -285,6 +285,7 @@ class(#character) String(Array)
|
||||
method(#primitive) strlen.
|
||||
|
||||
method(#primitive,#variadic) strfmt().
|
||||
method(#primitive,#variadic,#class) format(fmt).
|
||||
}
|
||||
|
||||
## -------------------------------------------------------------------------------
|
||||
|
@ -3637,6 +3637,29 @@ static moo_pfrc_t pf_error_as_string (moo_t* moo, moo_mod_t* mod, moo_ooi_t narg
|
||||
return MOO_PF_SUCCESS;
|
||||
}
|
||||
|
||||
static moo_pfrc_t pf_string_format (moo_t* moo, moo_mod_t* mod, moo_ooi_t nargs)
|
||||
{
|
||||
/* ignore the receiver. the first argument is the format string. */
|
||||
/*moo_oop_t rcv;
|
||||
rcv = MOO_STACK_GETRCV(moo, nargs);
|
||||
MOO_PF_CHECK_RCV (moo, MOO_OBJ_IS_CHAR_POINTER(rcv));*/
|
||||
|
||||
if (moo_strfmtcallstack(moo, nargs, 0) <= -1)
|
||||
{
|
||||
MOO_STACK_SETRETTOERRNUM (moo, nargs);
|
||||
}
|
||||
else
|
||||
{
|
||||
moo_oop_t str;
|
||||
str = moo_makestring(moo, moo->sprintf.xbuf.ptr, moo->sprintf.xbuf.len);
|
||||
if (!str) return MOO_PF_FAILURE;
|
||||
|
||||
MOO_STACK_SETRET (moo, nargs, str);
|
||||
}
|
||||
|
||||
return MOO_PF_SUCCESS;
|
||||
}
|
||||
|
||||
static moo_pfrc_t pf_strfmt (moo_t* moo, moo_mod_t* mod, moo_ooi_t nargs)
|
||||
{
|
||||
moo_oop_t rcv;
|
||||
@ -3644,7 +3667,7 @@ static moo_pfrc_t pf_strfmt (moo_t* moo, moo_mod_t* mod, moo_ooi_t nargs)
|
||||
rcv = MOO_STACK_GETRCV(moo, nargs);
|
||||
MOO_PF_CHECK_RCV (moo, MOO_OBJ_IS_CHAR_POINTER(rcv));
|
||||
|
||||
if (moo_sprintfmtst(moo, nargs) <= -1)
|
||||
if (moo_strfmtcallstack(moo, nargs, 1) <= -1)
|
||||
{
|
||||
MOO_STACK_SETRETTOERRNUM (moo, nargs);
|
||||
}
|
||||
@ -3870,6 +3893,7 @@ static pf_t pftab[] =
|
||||
{ "SmallPointer_putUint64", { moo_pf_smptr_put_uint64, 2, 2 } },
|
||||
{ "SmallPointer_putUint8", { moo_pf_smptr_put_uint8, 2, 2 } },
|
||||
|
||||
{ "String_format", { pf_string_format, 1, MA } },
|
||||
{ "String_strfmt", { pf_strfmt, 0, MA } },
|
||||
{ "String_strlen", { pf_strlen, 0, 0 } },
|
||||
|
||||
|
685
moo/lib/fmt.c
685
moo/lib/fmt.c
@ -1759,3 +1759,688 @@ moo_ooi_t moo_logufmt (moo_t* moo, moo_bitmask_t mask, const moo_uch_t* fmt, ...
|
||||
}
|
||||
return (x <= -1)? -1: fo.count;
|
||||
}
|
||||
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
* SUPPORT FOR FORMATTED OUTPUT TO BE USED BY BUILTIN PRIMITIVE FUNCTIONS
|
||||
* -------------------------------------------------------------------------- */
|
||||
static int sprint_bcs (moo_fmtout_t* fmtout, const moo_bch_t* ptr, moo_oow_t len)
|
||||
{
|
||||
moo_t* moo = (moo_t*)fmtout->ctx;
|
||||
moo_oow_t unused, oolen, blen;
|
||||
|
||||
unused = moo->sprintf.xbuf.capa - moo->sprintf.xbuf.len;
|
||||
|
||||
#if defined(MOO_OOCH_IS_UCH)
|
||||
blen = len;
|
||||
moo_conv_bchars_to_uchars_with_cmgr (ptr, &blen, MOO_NULL, &oolen, moo->cmgr, 1);
|
||||
#else
|
||||
oolen = len;
|
||||
#endif
|
||||
|
||||
if (oolen > unused)
|
||||
{
|
||||
moo_ooch_t* tmp;
|
||||
moo_oow_t newcapa;
|
||||
|
||||
newcapa = moo->sprintf.xbuf.len + oolen + 1;
|
||||
newcapa = MOO_ALIGN_POW2(newcapa, 256);
|
||||
|
||||
tmp = (moo_ooch_t*)moo_reallocmem(moo, moo->sprintf.xbuf.ptr, newcapa * MOO_SIZEOF(*tmp));
|
||||
if (!tmp) return -1;
|
||||
|
||||
moo->sprintf.xbuf.ptr = tmp;
|
||||
moo->sprintf.xbuf.capa = newcapa;
|
||||
}
|
||||
|
||||
#if defined(MOO_OOCH_IS_UCH)
|
||||
moo_conv_bchars_to_uchars_with_cmgr (ptr, &len, &moo->sprintf.xbuf.ptr[moo->sprintf.xbuf.len], &oolen, moo->cmgr, 1);
|
||||
#else
|
||||
MOO_MEMCPY (&moo->sprintf.xbuf.ptr[moo->sprintf.xbuf.len], ptr, len * MOO_SIZEOF(*ptr));
|
||||
#endif
|
||||
moo->sprintf.xbuf.len += oolen;
|
||||
|
||||
return 1; /* success */
|
||||
}
|
||||
|
||||
static int sprint_ucs (moo_fmtout_t* fmtout, const moo_uch_t* ptr, moo_oow_t len)
|
||||
{
|
||||
moo_t* moo = (moo_t*)fmtout->ctx;
|
||||
moo_oow_t unused, oolen, ulen;
|
||||
|
||||
unused = moo->sprintf.xbuf.capa - moo->sprintf.xbuf.len;
|
||||
|
||||
#if defined(MOO_OOCH_IS_UCH)
|
||||
oolen = len;
|
||||
#else
|
||||
ulen = len;
|
||||
moo_conv_uchars_to_bchars_with_cmgr (ptr, &ulen, MOO_NULL, &oolen, moo->cmgr);
|
||||
#endif
|
||||
|
||||
if (oolen > unused)
|
||||
{
|
||||
moo_ooch_t* tmp;
|
||||
moo_oow_t newcapa;
|
||||
|
||||
newcapa = moo->sprintf.xbuf.len + oolen + 1;
|
||||
newcapa = MOO_ALIGN_POW2(newcapa, 256);
|
||||
|
||||
tmp = (moo_ooch_t*)moo_reallocmem(moo, moo->sprintf.xbuf.ptr, newcapa * MOO_SIZEOF(*tmp));
|
||||
if (!tmp) return -1;
|
||||
|
||||
moo->sprintf.xbuf.ptr = tmp;
|
||||
moo->sprintf.xbuf.capa = newcapa;
|
||||
}
|
||||
|
||||
#if defined(MOO_OOCH_IS_UCH)
|
||||
MOO_MEMCPY (&moo->sprintf.xbuf.ptr[moo->sprintf.xbuf.len], ptr, len * MOO_SIZEOF(*ptr));
|
||||
#else
|
||||
moo_conv_uchars_to_bchars_with_cmgr (ptr, &len, &moo->sprintf.xbuf.ptr[moo->sprintf.xbuf.len], &oolen, moo->cmgr);
|
||||
#endif
|
||||
moo->sprintf.xbuf.len += oolen;
|
||||
|
||||
return 1; /* success */
|
||||
}
|
||||
|
||||
|
||||
moo_ooi_t moo_sproutbfmt (moo_t* moo, moo_bitmask_t mask, const moo_bch_t* fmt, ...)
|
||||
{
|
||||
int x;
|
||||
va_list ap;
|
||||
moo_fmtout_t fo;
|
||||
|
||||
MOO_MEMSET (&fo, 0, MOO_SIZEOF(fo));
|
||||
fo.fmt_type = MOO_FMTOUT_FMT_TYPE_BCH;
|
||||
fo.fmt_str = fmt;
|
||||
fo.mask = mask;
|
||||
fo.putbcs = sprint_bcs;
|
||||
fo.putucs = sprint_ucs;
|
||||
fo.putobj = moo_fmt_object_;
|
||||
|
||||
va_start (ap, fmt);
|
||||
x = fmt_outv(&fo, ap);
|
||||
va_end (ap);
|
||||
|
||||
return (x <= -1)? -1: fo.count;
|
||||
}
|
||||
|
||||
moo_ooi_t moo_sproutufmt (moo_t* moo, moo_bitmask_t mask, const moo_uch_t* fmt, ...)
|
||||
{
|
||||
int x;
|
||||
va_list ap;
|
||||
moo_fmtout_t fo;
|
||||
|
||||
MOO_MEMSET (&fo, 0, MOO_SIZEOF(fo));
|
||||
fo.fmt_type = MOO_FMTOUT_FMT_TYPE_UCH;
|
||||
fo.fmt_str = fmt;
|
||||
fo.mask = mask;
|
||||
fo.putbcs = sprint_bcs;
|
||||
fo.putucs = sprint_ucs;
|
||||
fo.putobj = moo_fmt_object_;
|
||||
|
||||
va_start (ap, fmt);
|
||||
x = fmt_outv(&fo, ap);
|
||||
va_end (ap);
|
||||
|
||||
return (x <= -1)? -1: fo.count;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#define GET_NEXT_ARG_TO(moo,nargs,arg_state,arg) do { \
|
||||
if ((arg_state)->idx >= nargs) { (arg_state)->stop = 1; goto invalid_format; } \
|
||||
arg = MOO_STACK_GETARG(moo, nargs, (arg_state)->idx); \
|
||||
(arg_state)->idx++; \
|
||||
} while(0)
|
||||
|
||||
#define GET_NEXT_CHAR_TO(moo,fmt,fmtend,ch) do { \
|
||||
if (fmt >= fmtend) ch = MOO_OOCI_EOF; \
|
||||
else { ch = *(fmt); (fmt)++; }\
|
||||
} while(0)
|
||||
|
||||
static MOO_INLINE int format_stack_args (moo_fmtout_t* fmtout, moo_ooi_t nargs, int rcv_is_fmtstr)
|
||||
{
|
||||
moo_t* moo = (moo_t*)fmtout->ctx;
|
||||
|
||||
const moo_ooch_t* fmtptr, * fmtend;
|
||||
const moo_ooch_t* checkpoint, * percent;
|
||||
|
||||
int n, radix, neg, sign, radix_flags;
|
||||
moo_ooi_t extra, width, precision;
|
||||
moo_ooch_t padc, ooch;
|
||||
moo_ooci_t ch;
|
||||
int flagc;
|
||||
|
||||
struct
|
||||
{
|
||||
moo_ooi_t idx;
|
||||
int stop;
|
||||
} arg_state;
|
||||
moo_oop_t arg;
|
||||
|
||||
MOO_ASSERT (moo, fmtout->putobj != MOO_NULL);
|
||||
|
||||
fmtout->count = 0;
|
||||
|
||||
if (rcv_is_fmtstr)
|
||||
{
|
||||
arg = MOO_STACK_GETRCV(moo, nargs);
|
||||
arg_state.idx = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
arg = MOO_STACK_GETARG(moo, nargs, 0);
|
||||
arg_state.idx = 1;
|
||||
}
|
||||
|
||||
if (!MOO_OOP_IS_POINTER(arg) || MOO_OBJ_GET_FLAGS_TYPE(arg) != MOO_OBJ_TYPE_CHAR)
|
||||
{
|
||||
moo_ooi_t i;
|
||||
/* if the first argument is not a valid formatting string,
|
||||
* print all arguments as objects */
|
||||
if (fmtout->putobj(fmtout, arg) <= -1) goto oops;
|
||||
for (i = arg_state.idx; i < nargs; i++)
|
||||
{
|
||||
arg = MOO_STACK_GETARG(moo, nargs, i);
|
||||
if (fmtout->putobj(fmtout, arg) <= -1) goto oops;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
arg_state.stop = 0;
|
||||
|
||||
fmtptr = MOO_OBJ_GET_CHAR_SLOT(arg);
|
||||
fmtend = fmtptr + MOO_OBJ_GET_SIZE(arg);
|
||||
|
||||
while (1)
|
||||
{
|
||||
checkpoint = fmtptr;
|
||||
|
||||
while (1)
|
||||
{
|
||||
GET_NEXT_CHAR_TO (moo, fmtptr, fmtend, ch);
|
||||
if (ch == '%' && !arg_state.stop) break;
|
||||
|
||||
if (ch == MOO_OOCI_EOF)
|
||||
{
|
||||
/* fmt is not advanced when it is length-bounded.
|
||||
* so not fmt - checkpoint - 1 */
|
||||
PUT_OOCS (fmtout, checkpoint, fmtptr - checkpoint);
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
PUT_OOCS (fmtout, checkpoint, fmtptr - checkpoint - 1);
|
||||
|
||||
percent = fmtptr - 1;
|
||||
|
||||
padc = ' ';
|
||||
width = 0; precision = 0;
|
||||
neg = 0; sign = 0;
|
||||
|
||||
flagc = 0;
|
||||
radix_flags = MOO_INTTOSTR_NONEWOBJ;
|
||||
|
||||
reswitch:
|
||||
GET_NEXT_CHAR_TO (moo, fmtptr, fmtend, ch);
|
||||
switch (ch)
|
||||
{
|
||||
case '%': /* %% */
|
||||
ooch = ch;
|
||||
goto print_char;
|
||||
|
||||
/* flag characters */
|
||||
case '.':
|
||||
if (flagc & FLAGC_DOT) goto invalid_format;
|
||||
flagc |= FLAGC_DOT;
|
||||
goto reswitch;
|
||||
|
||||
case '#':
|
||||
if (flagc & (FLAGC_WIDTH | FLAGC_DOT | FLAGC_LENMOD)) goto invalid_format;
|
||||
flagc |= FLAGC_SHARP;
|
||||
goto reswitch;
|
||||
|
||||
case ' ':
|
||||
if (flagc & (FLAGC_WIDTH | FLAGC_DOT | FLAGC_LENMOD)) goto invalid_format;
|
||||
flagc |= FLAGC_SPACE;
|
||||
goto reswitch;
|
||||
|
||||
case '+': /* place sign for signed conversion */
|
||||
if (flagc & (FLAGC_WIDTH | FLAGC_DOT | FLAGC_LENMOD)) goto invalid_format;
|
||||
flagc |= FLAGC_SIGN;
|
||||
goto reswitch;
|
||||
|
||||
case '-': /* left adjusted */
|
||||
if (flagc & (FLAGC_WIDTH | FLAGC_DOT | FLAGC_LENMOD)) goto invalid_format;
|
||||
if (flagc & FLAGC_DOT)
|
||||
{
|
||||
goto invalid_format;
|
||||
}
|
||||
else
|
||||
{
|
||||
flagc |= FLAGC_LEFTADJ;
|
||||
if (flagc & FLAGC_ZEROPAD)
|
||||
{
|
||||
padc = ' ';
|
||||
flagc &= ~FLAGC_ZEROPAD;
|
||||
}
|
||||
}
|
||||
|
||||
goto reswitch;
|
||||
|
||||
case '*': /* take the length from the parameter */
|
||||
if (flagc & FLAGC_DOT)
|
||||
{
|
||||
if (flagc & (FLAGC_STAR2 | FLAGC_PRECISION)) goto invalid_format;
|
||||
flagc |= FLAGC_STAR2;
|
||||
|
||||
GET_NEXT_ARG_TO (moo, nargs, &arg_state, arg);
|
||||
if (moo_inttoooi(moo, arg, &precision) <= -1) goto invalid_format;
|
||||
if (precision < 0)
|
||||
{
|
||||
/* if precision is less than 0,
|
||||
* treat it as if no .precision is specified */
|
||||
flagc &= ~FLAGC_DOT;
|
||||
precision = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (flagc & (FLAGC_STAR1 | FLAGC_WIDTH)) goto invalid_format;
|
||||
flagc |= FLAGC_STAR1;
|
||||
|
||||
GET_NEXT_ARG_TO (moo, nargs, &arg_state, arg);
|
||||
if (moo_inttoooi(moo, arg, &width) <= -1) goto invalid_format;
|
||||
if (width < 0)
|
||||
{
|
||||
flagc |= FLAGC_LEFTADJ;
|
||||
width = -width;
|
||||
}
|
||||
}
|
||||
goto reswitch;
|
||||
|
||||
case '0': /* zero pad */
|
||||
if (flagc & FLAGC_LENMOD) goto invalid_format;
|
||||
if (!(flagc & (FLAGC_DOT | FLAGC_LEFTADJ)))
|
||||
{
|
||||
padc = '0';
|
||||
flagc |= FLAGC_ZEROPAD;
|
||||
goto reswitch;
|
||||
}
|
||||
/* end of flags characters */
|
||||
|
||||
case '1': case '2': case '3': case '4':
|
||||
case '5': case '6': case '7': case '8': case '9':
|
||||
if (flagc & FLAGC_LENMOD) goto invalid_format;
|
||||
for (n = 0;; ++fmtptr)
|
||||
{
|
||||
n = n * 10 + ch - '0';
|
||||
ch = *fmtptr;
|
||||
if (ch < '0' || ch > '9') break;
|
||||
}
|
||||
if (flagc & FLAGC_DOT)
|
||||
{
|
||||
if (flagc & FLAGC_STAR2) goto invalid_format;
|
||||
precision = n;
|
||||
flagc |= FLAGC_PRECISION;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (flagc & FLAGC_STAR1) goto invalid_format;
|
||||
width = n;
|
||||
flagc |= FLAGC_WIDTH;
|
||||
}
|
||||
goto reswitch;
|
||||
|
||||
/* integer conversions */
|
||||
case 'd':
|
||||
case 'i': /* signed conversion */
|
||||
radix = 10;
|
||||
sign = 1;
|
||||
goto print_integer;
|
||||
case 'o':
|
||||
radix = 8;
|
||||
goto print_integer;
|
||||
case 'u':
|
||||
radix = 10;
|
||||
goto print_integer;
|
||||
case 'x':
|
||||
radix_flags |= MOO_INTTOSTR_LOWERCASE;
|
||||
case 'X':
|
||||
radix = 16;
|
||||
goto print_integer;
|
||||
case 'b':
|
||||
radix = 2;
|
||||
goto print_integer;
|
||||
/* end of integer conversions */
|
||||
|
||||
case 'f':
|
||||
{
|
||||
const moo_ooch_t* nsptr;
|
||||
moo_oow_t nslen;
|
||||
moo_oow_t scale = 0;
|
||||
|
||||
GET_NEXT_ARG_TO (moo, nargs, &arg_state, arg);
|
||||
if (MOO_OOP_IS_CHAR(arg))
|
||||
{
|
||||
arg = MOO_SMOOI_TO_OOP(MOO_OOP_TO_CHAR(arg));
|
||||
}
|
||||
else if (MOO_OOP_IS_FPDEC(moo, arg))
|
||||
{
|
||||
moo_oop_fpdec_t fa = (moo_oop_fpdec_t)arg;
|
||||
scale = MOO_OOP_TO_SMOOI(fa->scale);
|
||||
arg = fa->value;
|
||||
}
|
||||
|
||||
if (!moo_inttostr(moo, arg, 10 | MOO_INTTOSTR_NONEWOBJ))
|
||||
{
|
||||
MOO_LOG1 (moo, MOO_LOG_WARN | MOO_LOG_UNTYPED, "unable to convert %O to string \n", arg);
|
||||
goto invalid_format;
|
||||
}
|
||||
|
||||
nsptr = moo->inttostr.xbuf.ptr;
|
||||
nslen = moo->inttostr.xbuf.len;
|
||||
MOO_ASSERT (moo, nslen > 0);
|
||||
|
||||
if (nsptr[0] == '-')
|
||||
{
|
||||
MOO_ASSERT (moo, (MOO_OOP_IS_SMOOI(arg) && MOO_OOP_TO_SMOOI(arg) < 0) || MOO_OOP_IS_NBIGINT(moo,arg));
|
||||
nsptr++;
|
||||
nslen--;
|
||||
neg = 1;
|
||||
}
|
||||
|
||||
if (!(flagc & FLAGC_DOT))
|
||||
{
|
||||
precision = scale;
|
||||
if (precision <= 0) precision = 1;
|
||||
}
|
||||
|
||||
if ((flagc & FLAGC_DOT) && precision < scale)
|
||||
{
|
||||
moo_oow_t diff = scale - precision;
|
||||
scale = precision;
|
||||
nslen = (nslen < diff)? 0: (nslen - diff);
|
||||
}
|
||||
|
||||
if (nslen < scale + 1)
|
||||
{
|
||||
extra = 1;
|
||||
if (precision > 0) extra += 1 + scale;
|
||||
}
|
||||
else
|
||||
{
|
||||
extra = 0;
|
||||
if (nslen > 0) extra += nslen - scale;
|
||||
if (precision > 0)
|
||||
{
|
||||
extra += 1;
|
||||
if (nslen > 0) extra += scale;
|
||||
}
|
||||
}
|
||||
|
||||
if (neg) extra++;
|
||||
else if (flagc & FLAGC_SIGN) extra++;
|
||||
else if (flagc & FLAGC_SPACE) extra++;
|
||||
|
||||
if ((flagc & FLAGC_DOT) && precision > scale)
|
||||
{
|
||||
/* trailing zeros in the fractional part */
|
||||
extra += precision - scale;
|
||||
}
|
||||
|
||||
if (!(flagc & FLAGC_LEFTADJ) && !(flagc & FLAGC_ZEROPAD) && width > extra)
|
||||
{
|
||||
width -= extra;
|
||||
PUT_OOCH (fmtout, padc, width);
|
||||
width = 0;
|
||||
}
|
||||
if (neg) PUT_OOCH (fmtout, '-', 1);
|
||||
else if (flagc & FLAGC_SIGN) PUT_OOCH (fmtout, '+', 1);
|
||||
else if (flagc & FLAGC_SPACE) PUT_OOCH (fmtout, ' ', 1);
|
||||
|
||||
if (!(flagc & FLAGC_LEFTADJ) && width > extra)
|
||||
{
|
||||
width -= extra;
|
||||
PUT_OOCH (fmtout, padc, width);
|
||||
}
|
||||
|
||||
if (nslen < scale + 1)
|
||||
{
|
||||
PUT_OOCH (fmtout, '0', 1);
|
||||
if (precision > 0)
|
||||
{
|
||||
PUT_OOCH (fmtout, '.', 1);
|
||||
PUT_OOCH (fmtout, '0', scale - nslen);
|
||||
PUT_OOCS (fmtout, nsptr, nslen);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (nslen > 0) PUT_OOCS (fmtout, nsptr, nslen - scale);
|
||||
if (precision > 0)
|
||||
{
|
||||
PUT_OOCH (fmtout, '.', 1);
|
||||
if (nslen > 0) PUT_OOCS (fmtout, &nsptr[nslen - scale], scale);
|
||||
}
|
||||
}
|
||||
if (precision > scale)
|
||||
{
|
||||
/* trailing zeros in the fractional part */
|
||||
PUT_OOCH (fmtout, '0', precision - scale);
|
||||
}
|
||||
|
||||
if ((flagc & FLAGC_LEFTADJ) && width > extra)
|
||||
{
|
||||
width -= extra;
|
||||
PUT_OOCH (fmtout, padc, width);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 'c':
|
||||
case 'C':
|
||||
GET_NEXT_ARG_TO (moo, nargs, &arg_state, arg);
|
||||
if (MOO_OOP_IS_SMOOI(arg)) arg = MOO_CHAR_TO_OOP(MOO_OOP_TO_SMOOI(arg));
|
||||
if (!MOO_OOP_IS_CHAR(arg)) goto invalid_format;
|
||||
ooch = MOO_OOP_TO_CHAR(arg);
|
||||
|
||||
print_char:
|
||||
/* zeropad must not take effect for 'c' */
|
||||
if (flagc & FLAGC_ZEROPAD) padc = ' ';
|
||||
|
||||
/* precision 0 doesn't kill the letter */
|
||||
width--;
|
||||
if (!(flagc & FLAGC_LEFTADJ) && width > 0) PUT_OOCH (fmtout, padc, width);
|
||||
PUT_OOCH (fmtout, ooch, 1);
|
||||
if ((flagc & FLAGC_LEFTADJ) && width > 0) PUT_OOCH (fmtout, padc, width);
|
||||
break;
|
||||
|
||||
case 's':
|
||||
case 'S':
|
||||
{
|
||||
const moo_ooch_t* oosp;
|
||||
moo_oow_t oosl;
|
||||
|
||||
/* zeropad must not take effect for 'S' */
|
||||
if (flagc & FLAGC_ZEROPAD) padc = ' ';
|
||||
|
||||
GET_NEXT_ARG_TO (moo, nargs, &arg_state, arg);
|
||||
if (!MOO_OOP_IS_POINTER(arg) || MOO_OBJ_GET_FLAGS_TYPE(arg) != MOO_OBJ_TYPE_CHAR) goto invalid_format;
|
||||
|
||||
oosp = MOO_OBJ_GET_CHAR_SLOT(arg);
|
||||
oosl = MOO_OBJ_GET_SIZE(arg);
|
||||
|
||||
if (flagc & FLAGC_DOT)
|
||||
{
|
||||
if (oosl > precision) oosl = precision;
|
||||
}
|
||||
width -= oosl;
|
||||
|
||||
if (!(flagc & FLAGC_LEFTADJ) && width > 0) PUT_OOCH (fmtout, padc, width);
|
||||
PUT_OOCS (fmtout, oosp, oosl);
|
||||
if ((flagc & FLAGC_LEFTADJ) && width > 0) PUT_OOCH (fmtout, padc, width);
|
||||
break;
|
||||
}
|
||||
|
||||
case 'O': /* object - ignore precision, width, adjustment */
|
||||
GET_NEXT_ARG_TO (moo, nargs, &arg_state, arg);
|
||||
if (fmtout->putobj(fmtout, arg) <= -1) goto oops;
|
||||
break;
|
||||
|
||||
print_integer:
|
||||
{
|
||||
const moo_ooch_t* nsptr;
|
||||
moo_oow_t nslen;
|
||||
|
||||
GET_NEXT_ARG_TO (moo, nargs, &arg_state, arg);
|
||||
if (MOO_OOP_IS_CHAR(arg))
|
||||
{
|
||||
arg = MOO_SMOOI_TO_OOP(MOO_OOP_TO_CHAR(arg));
|
||||
}
|
||||
else if (MOO_OOP_IS_FPDEC(moo, arg))
|
||||
{
|
||||
moo_oop_t nv;
|
||||
moo_oop_fpdec_t fa = (moo_oop_fpdec_t)arg;
|
||||
|
||||
/* the given number for integer output is a fixed-point decimal.
|
||||
* i will drop all digits after the fixed point */
|
||||
moo_pushvolat (moo, &arg);
|
||||
nv = moo_truncfpdecval(moo, fa->value, MOO_OOP_TO_SMOOI(fa->scale), 0);
|
||||
moo_popvolat (moo);
|
||||
if (!nv)
|
||||
{
|
||||
MOO_LOG1 (moo, MOO_LOG_WARN | MOO_LOG_UNTYPED, "unable to truncate a fixed-point number %O to an integer for output\n", arg);
|
||||
goto invalid_format;
|
||||
}
|
||||
|
||||
arg = nv;
|
||||
}
|
||||
|
||||
if (!moo_inttostr(moo, arg, radix | radix_flags))
|
||||
{
|
||||
/*moo_seterrbfmt (moo, MOO_EINVAL, "not a valid number - %O", arg);
|
||||
goto oops;*/
|
||||
MOO_LOG1 (moo, MOO_LOG_WARN | MOO_LOG_UNTYPED, "unable to convert integer %O to string \n", arg);
|
||||
goto invalid_format;
|
||||
}
|
||||
|
||||
nsptr = moo->inttostr.xbuf.ptr;
|
||||
nslen = moo->inttostr.xbuf.len;
|
||||
|
||||
MOO_ASSERT (moo, nslen > 0);
|
||||
if (nsptr[0] == '-')
|
||||
{
|
||||
/* a negative number was given. i must skip the minus sign
|
||||
* added by moo_inttostr() for a negative number. */
|
||||
MOO_ASSERT (moo, (MOO_OOP_IS_SMOOI(arg) && MOO_OOP_TO_SMOOI(arg) < 0) || MOO_OOP_IS_NBIGINT(moo,arg));
|
||||
nsptr++;
|
||||
nslen--;
|
||||
}
|
||||
|
||||
extra = nslen;
|
||||
if (sign && ((MOO_OOP_IS_SMOOI(arg) && MOO_OOP_TO_SMOOI(arg) < 0) || MOO_OOP_IS_NBIGINT(moo,arg))) neg = 1;
|
||||
|
||||
if ((flagc & FLAGC_SHARP) && arg != MOO_SMOOI_TO_OOP(0))
|
||||
{
|
||||
if (radix == 2 || radix == 8 || radix == 16) extra += 2;
|
||||
}
|
||||
if (neg) extra++;
|
||||
else if (flagc & FLAGC_SIGN) extra++;
|
||||
else if (flagc & FLAGC_SPACE) extra++;
|
||||
|
||||
if ((flagc & FLAGC_DOT) && precision > nslen)
|
||||
{
|
||||
/* extra zeros for precision specified */
|
||||
extra += (precision - nslen);
|
||||
}
|
||||
|
||||
if (!(flagc & FLAGC_LEFTADJ) && !(flagc & FLAGC_ZEROPAD) && width > 0 && (width -= extra) > 0)
|
||||
{
|
||||
PUT_OOCH (fmtout, padc, width);
|
||||
width = 0;
|
||||
}
|
||||
|
||||
if (neg) PUT_OOCH (fmtout, '-', 1);
|
||||
else if (flagc & FLAGC_SIGN) PUT_OOCH (fmtout, '+', 1);
|
||||
else if (flagc & FLAGC_SPACE) PUT_OOCH (fmtout, ' ', 1);
|
||||
|
||||
if ((flagc & FLAGC_SHARP) && arg != MOO_SMOOI_TO_OOP(0))
|
||||
{
|
||||
if (radix == 2)
|
||||
{
|
||||
PUT_OOCH (fmtout, '2', 1);
|
||||
PUT_OOCH (fmtout, 'r', 1);
|
||||
}
|
||||
if (radix == 8)
|
||||
{
|
||||
PUT_OOCH (fmtout, '8', 1);
|
||||
PUT_OOCH (fmtout, 'r', 1);
|
||||
}
|
||||
else if (radix == 16)
|
||||
{
|
||||
PUT_OOCH (fmtout, '1', 1);
|
||||
PUT_OOCH (fmtout, '6', 1);
|
||||
PUT_OOCH (fmtout, 'r', 1);
|
||||
}
|
||||
}
|
||||
|
||||
if ((flagc & FLAGC_DOT) && precision > nslen)
|
||||
{
|
||||
/* extra zeros for precision specified */
|
||||
PUT_OOCH (fmtout, '0', precision - nslen);
|
||||
}
|
||||
|
||||
if (!(flagc & FLAGC_LEFTADJ) && width > 0 && (width -= extra) > 0)
|
||||
{
|
||||
PUT_OOCH (fmtout, padc, width);
|
||||
}
|
||||
|
||||
PUT_OOCS (fmtout, nsptr, nslen);
|
||||
|
||||
if ((flagc & FLAGC_LEFTADJ) && width > 0 && (width -= extra) > 0)
|
||||
{
|
||||
PUT_OOCH (fmtout, padc, width);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
invalid_format:
|
||||
PUT_OOCS (fmtout, percent, fmtptr - percent);
|
||||
break;
|
||||
|
||||
default:
|
||||
PUT_OOCS (fmtout, percent, fmtptr - percent);
|
||||
/*
|
||||
* Since we ignore an formatting argument it is no
|
||||
* longer safe to obey the remaining formatting
|
||||
* arguments as the arguments will no longer match
|
||||
* the format specs.
|
||||
*/
|
||||
arg_state.stop = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
done:
|
||||
return 0;
|
||||
|
||||
oops:
|
||||
return -1;
|
||||
}
|
||||
|
||||
int moo_strfmtcallstack (moo_t* moo, moo_ooi_t nargs, int rcv_is_fmtstr)
|
||||
{
|
||||
/* format a string using the receiver and arguments on the stack */
|
||||
moo_fmtout_t fo;
|
||||
|
||||
MOO_MEMSET (&fo, 0, MOO_SIZEOF(fo));
|
||||
fo.ctx = moo;
|
||||
fo.putbcs = sprint_bcs;
|
||||
fo.putucs = sprint_ucs;
|
||||
fo.putobj = moo_fmt_object_;
|
||||
/* format_stack_args doesn't use fmt_str and fmt_type.
|
||||
* it takes the format string from the stack. */
|
||||
|
||||
moo->sprintf.xbuf.len = 0;
|
||||
return format_stack_args(&fo, nargs, rcv_is_fmtstr);
|
||||
}
|
||||
|
@ -26,6 +26,8 @@
|
||||
|
||||
#include "moo-prv.h"
|
||||
|
||||
#if 0
|
||||
|
||||
/*#include <stdio.h>*/ /* for snrintf(). used for floating-point number formatting */
|
||||
|
||||
#if defined(_MSC_VER) || defined(__BORLANDC__) || (defined(__WATCOMC__) && (__WATCOMC__ < 1200))
|
||||
@ -729,7 +731,7 @@ moo_ooi_t moo_logufmt (moo_t* moo, moo_bitmask_t mask, const moo_uch_t* fmt, ...
|
||||
else { ch = *(fmt); (fmt)++; }\
|
||||
} while(0)
|
||||
|
||||
static MOO_INLINE int print_formatted (moo_t* moo, moo_ooi_t nargs, moo_fmtout_data_t* data, moo_outbfmt_t outbfmt, int ignore_rcv)
|
||||
static MOO_INLINE int print_formatted (moo_t* moo, moo_ooi_t nargs, moo_fmtout_data_t* data, moo_outbfmt_t outbfmt, int rcv_is_fmtstr)
|
||||
{
|
||||
const moo_ooch_t* fmt, * fmtend;
|
||||
const moo_ooch_t* checkpoint, * percent;
|
||||
@ -747,16 +749,16 @@ static MOO_INLINE int print_formatted (moo_t* moo, moo_ooi_t nargs, moo_fmtout_d
|
||||
} arg_state;
|
||||
moo_oop_t arg;
|
||||
|
||||
if (ignore_rcv)
|
||||
{
|
||||
arg = MOO_STACK_GETARG(moo, nargs, 0);
|
||||
arg_state.idx = 1;
|
||||
}
|
||||
else
|
||||
if (rcv_is_fmtstr)
|
||||
{
|
||||
arg = MOO_STACK_GETRCV(moo, nargs);
|
||||
arg_state.idx = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
arg = MOO_STACK_GETARG(moo, nargs, 0);
|
||||
arg_state.idx = 1;
|
||||
}
|
||||
|
||||
if (!MOO_OOP_IS_POINTER(arg) || MOO_OBJ_GET_FLAGS_TYPE(arg) != MOO_OBJ_TYPE_CHAR)
|
||||
{
|
||||
@ -1377,6 +1379,7 @@ static moo_ooi_t __sprbfmtv(moo_t* moo, moo_bitmask_t mask, const moo_bch_t* fmt
|
||||
return fo.count;
|
||||
}
|
||||
|
||||
#if 0
|
||||
moo_ooi_t moo_sproutbfmt (moo_t* moo, moo_bitmask_t mask, const moo_bch_t* fmt, ...)
|
||||
{
|
||||
int x;
|
||||
@ -1393,7 +1396,7 @@ moo_ooi_t moo_sproutbfmt (moo_t* moo, moo_bitmask_t mask, const moo_bch_t* fmt,
|
||||
|
||||
return (x <= -1)? -1: fo.count;
|
||||
}
|
||||
|
||||
#endif
|
||||
/*
|
||||
moo_ooi_t moo_sproutufmt (moo_t* moo, moo_bitmask_t mask, const moo_uch_t* fmt, ...)
|
||||
{
|
||||
@ -1413,7 +1416,7 @@ moo_ooi_t moo_sproutufmt (moo_t* moo, moo_bitmask_t mask, const moo_uch_t* fmt,
|
||||
}*/
|
||||
|
||||
|
||||
int moo_sprintfmtst (moo_t* moo, moo_ooi_t nargs)
|
||||
int moo_strfmtcallstack (moo_t* moo, moo_ooi_t nargs)
|
||||
{
|
||||
/* format a string using the receiver and arguments on the stack */
|
||||
moo_fmtout_data_t fo;
|
||||
@ -1421,5 +1424,7 @@ int moo_sprintfmtst (moo_t* moo, moo_ooi_t nargs)
|
||||
fo.putch = put_sprch;
|
||||
fo.putcs = put_sprcs;
|
||||
moo->sprintf.xbuf.len = 0;
|
||||
return print_formatted(moo, nargs, &fo, moo_sproutbfmt, 0);
|
||||
return print_formatted(moo, nargs, &fo, moo_sproutbfmt, 1);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -1501,9 +1501,10 @@ moo_ooi_t moo_sproutbfmt (
|
||||
...
|
||||
);
|
||||
|
||||
int moo_sprintfmtst (
|
||||
int moo_strfmtcallstack (
|
||||
moo_t* moo,
|
||||
moo_ooi_t nargs
|
||||
moo_ooi_t nargs,
|
||||
int rcv_is_fmtstr
|
||||
);
|
||||
|
||||
/* ========================================================================= */
|
||||
|
@ -381,10 +381,10 @@ MOO_EXPORT moo_oow_t moo_hash_bytes_ (
|
||||
}
|
||||
#else
|
||||
# define moo_hash_bytes(ptr,len) moo_hash_bytes_(ptr, len)
|
||||
# define moo_hash_bchars(ptr,len) moo_hash_bytes((const moo_oob_t*)(ptr), (len) * MOO_SIZEOF(moo_bch_t))
|
||||
# define moo_hash_uchars(ptr,len) moo_hash_bytes((const moo_oob_t*)(ptr), (len) * MOO_SIZEOF(moo_uch_t))
|
||||
# define moo_hash_words(ptr,len) moo_hash_bytes((const moo_oob_t*)(ptr), (len) * MOO_SIZEOF(moo_oow_t))
|
||||
# define moo_hash_halfwords(ptr,len) moo_hash_bytes((const moo_oob_t*)(ptr), (len) * MOO_SIZEOF(moo_oohw_t))
|
||||
# define moo_hash_bchars(ptr,len) moo_hash_bytes_((const moo_oob_t*)(ptr), (len) * MOO_SIZEOF(moo_bch_t))
|
||||
# define moo_hash_uchars(ptr,len) moo_hash_bytes_((const moo_oob_t*)(ptr), (len) * MOO_SIZEOF(moo_uch_t))
|
||||
# define moo_hash_words(ptr,len) moo_hash_bytes_((const moo_oob_t*)(ptr), (len) * MOO_SIZEOF(moo_oow_t))
|
||||
# define moo_hash_halfwords(ptr,len) moo_hash_bytes_((const moo_oob_t*)(ptr), (len) * MOO_SIZEOF(moo_oohw_t))
|
||||
#endif
|
||||
|
||||
#if defined(MOO_OOCH_IS_UCH)
|
||||
|
@ -332,6 +332,7 @@ pdfdir = @pdfdir@
|
||||
prefix = @prefix@
|
||||
program_transform_name = @program_transform_name@
|
||||
psdir = @psdir@
|
||||
runstatedir = @runstatedir@
|
||||
sbindir = @sbindir@
|
||||
sharedstatedir = @sharedstatedir@
|
||||
srcdir = @srcdir@
|
||||
|
@ -3,6 +3,7 @@
|
||||
#include <stdio.h>
|
||||
#include <wchar.h>
|
||||
#include <locale.h>
|
||||
#include "t.h"
|
||||
|
||||
static int put_bcs (moo_fmtout_t* fmtout, const moo_bch_t* c, moo_oow_t len)
|
||||
{
|
||||
@ -59,6 +60,11 @@ int main ()
|
||||
|
||||
/* this unit is the number of characters written. but some are written as bch and some other as uch.
|
||||
* if uch and bch data are mixed, the count returned doesn't really tell how many bytes or characters written */
|
||||
cnt = bfmt_out ("wrote [%ld] units\n", cnt);
|
||||
bfmt_out ("wrote [%ld] units\n", cnt);
|
||||
T_ASSERT1 (cnt == 98, "bfmt_out test #1");
|
||||
|
||||
return 0;
|
||||
|
||||
oops:
|
||||
return -1;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user