changed the second parameter of qse_awk_rtx_strtonum() to accept the base value on top of the 'strict' conversion bit.

enhanced awk's str::tonum() to accept the optional base parameter
This commit is contained in:
hyung-hwan 2018-09-26 05:41:37 +00:00
parent eb79fa721f
commit 5743a341cc
5 changed files with 55 additions and 22 deletions

View File

@ -2777,13 +2777,17 @@ QSE_EXPORT int qse_awk_rtx_valtoflt (
* memory pointed to by \a l; A string containng '.', 'E', or 'e' is
* converted to a floating-pointer number and it is stored into memory
* pointed to by \a r. If \a strict is 0, the function takes up to the last
* valid character and never fails. If \a strict is non-zero, an invalid
* valid character and never fails. If \a strict is 1, an invalid
* character causes the function to return an error.
*
* \return 0 if converted to an integer,
* 1 if converted to a floating-point number
* -1 on error.
*/
#define QSE_AWK_RTX_STRTONUM_MAKE_OPTION(strict,base) (((strict) & 1) | ((base) << 8))
#define QSE_AWK_RTX_STRTONUM_GET_OPTION_STRICT(option) ((option) & 1)
#define QSE_AWK_RTX_STRTONUN_GET_OPTION_BASE(option) ((option) >> 8)
QSE_EXPORT int qse_awk_rtx_strtonum (
qse_awk_rtx_t* rtx, /**< runtime context */
int strict, /**< determines to perform strict check */

View File

@ -29,6 +29,7 @@
#include <qse/cmn/chr.h>
#include "../cmn/mem-prv.h"
#include "fnc.h"
#include "val.h"
static int fnc_normspace (qse_awk_rtx_t* rtx, const qse_awk_fnc_info_t* fi)
{
@ -215,6 +216,7 @@ static int fnc_value (qse_awk_rtx_t* rtx, const qse_awk_fnc_info_t* fi)
static int fnc_tonum (qse_awk_rtx_t* rtx, const qse_awk_fnc_info_t* fi)
{
/* str::tonum (value) */
/* str::tonum (string, base) */
qse_awk_val_t* retv;
qse_awk_val_t* a0;
@ -224,18 +226,38 @@ static int fnc_tonum (qse_awk_rtx_t* rtx, const qse_awk_fnc_info_t* fi)
a0 = qse_awk_rtx_getarg(rtx, 0);
rx = qse_awk_rtx_valtonum (rtx, a0, &lv, &rv);
if (rx == 0)
if (QSE_AWK_RTX_GETVALTYPE(rtx, a0) == QSE_AWK_VAL_STR && qse_awk_rtx_getnargs(rtx) >= 2)
{
retv = qse_awk_rtx_makeintval (rtx, lv);
}
else if (rx >= 1)
{
retv = qse_awk_rtx_makefltval (rtx, rv);
/* if the value is known to be a string, it supports the optional
* base parameter */
qse_awk_val_t* a1 = qse_awk_rtx_getarg(rtx, 1);
qse_awk_int_t base;
if (qse_awk_rtx_valtoint(rtx, a1, &base) <= -1) return -1;
rx = qse_awk_rtx_strtonum (
rtx,
QSE_AWK_RTX_STRTONUM_MAKE_OPTION(0, base),
((qse_awk_val_str_t*)a0)->val.ptr,
((qse_awk_val_str_t*)a0)->val.len,
&lv, &rv
);
}
else
{
retv = qse_awk_rtx_makeintval (rtx, 0);
rx = qse_awk_rtx_valtonum(rtx, a0, &lv, &rv);
}
if (rx == 0)
{
retv = qse_awk_rtx_makeintval(rtx, lv);
}
else if (rx >= 1)
{
retv = qse_awk_rtx_makefltval(rtx, rv);
}
else
{
retv = qse_awk_rtx_makeintval(rtx, 0);
}
if (!retv) return -1;
@ -281,7 +303,7 @@ static fnctab_t fnctab[] =
{ QSE_T("sub"), { { 2, 3, QSE_T("xvr") }, qse_awk_fnc_sub, 0 } },
{ QSE_T("substr"), { { 2, 3, QSE_NULL }, qse_awk_fnc_substr, 0 } },
{ QSE_T("tolower"), { { 1, 1, QSE_NULL }, qse_awk_fnc_tolower, 0 } },
{ QSE_T("tonum"), { { 1, 1, QSE_NULL }, fnc_tonum, 0 } },
{ QSE_T("tonum"), { { 1, 2, QSE_NULL }, fnc_tonum, 0 } },
{ QSE_T("toupper"), { { 1, 1, QSE_NULL }, qse_awk_fnc_toupper, 0 } },
{ QSE_T("trim"), { { 1, 1, QSE_NULL }, fnc_trim, 0 } },
{ QSE_T("value"), { { 1, 1, QSE_NULL }, fnc_value, 0 } }

View File

@ -4204,7 +4204,8 @@ static QSE_INLINE int __cmp_int_str (
qse_awk_flt_t rr;
n = qse_awk_rtx_strtonum (
rtx, 1,
rtx,
QSE_AWK_RTX_STRTONUM_MAKE_OPTION(1, 0),
((qse_awk_val_str_t*)right)->val.ptr,
((qse_awk_val_str_t*)right)->val.len,
&ll, &rr

View File

@ -2185,9 +2185,9 @@ static int fnc_setioattr (qse_awk_rtx_t* rtx, const qse_awk_fnc_info_t* fi)
qse_awk_flt_t r;
int x;
/* no error is returned by qse_awk_rtx_strnum() if the second
* parameter is 0. so i don't check for an error */
x = qse_awk_rtx_strtonum (rtx, 0, ptr[2], len[2], &l, &r);
/* no error is returned by qse_awk_rtx_strnum() if the strict option
* of the second parameter is 0. so i don't check for an error */
x = qse_awk_rtx_strtonum(rtx, QSE_AWK_RTX_STRTONUM_MAKE_OPTION(0, 0), ptr[2], len[2], &l, &r);
if (x == 0) r = (qse_awk_flt_t)l;
ioattr = find_or_make_ioattr (rtx, &rxtn->cmgrtab, ptr[0], len[0]);

View File

@ -443,8 +443,8 @@ qse_awk_val_t* qse_awk_rtx_makenstrvalwithxstr (qse_awk_rtx_t* rtx, const qse_cs
qse_awk_int_t l;
qse_awk_flt_t r;
x = qse_awk_rtx_strtonum (rtx, 1, str->ptr, str->len, &l, &r);
v = qse_awk_rtx_makestrvalwithxstr (rtx, str);
x = qse_awk_rtx_strtonum(rtx, QSE_AWK_RTX_STRTONUM_MAKE_OPTION(1, 0), str->ptr, str->len, &l, &r);
v = qse_awk_rtx_makestrvalwithxstr(rtx, str);
if (v == QSE_NULL) return QSE_NULL;
@ -1555,7 +1555,8 @@ static int val_ref_to_num (
if (idx == 0)
{
return qse_awk_rtx_strtonum (
rtx, 0,
rtx,
QSE_AWK_RTX_STRTONUM_MAKE_OPTION(0, 0),
QSE_STR_PTR(&rtx->inrec.line),
QSE_STR_LEN(&rtx->inrec.line),
l, r
@ -1564,7 +1565,8 @@ static int val_ref_to_num (
else if (idx <= rtx->inrec.nflds)
{
return qse_awk_rtx_strtonum (
rtx, 0,
rtx,
QSE_AWK_RTX_STRTONUM_MAKE_OPTION(0, 0),
rtx->inrec.flds[idx-1].ptr,
rtx->inrec.flds[idx-1].len,
l, r
@ -1573,7 +1575,7 @@ static int val_ref_to_num (
else
{
return qse_awk_rtx_strtonum (
rtx, 0, QSE_T(""), 0, l, r
rtx, QSE_AWK_RTX_STRTONUM_MAKE_OPTION(0, 0), QSE_T(""), 0, l, r
);
}
}
@ -1628,7 +1630,8 @@ int qse_awk_rtx_valtonum (
case QSE_AWK_VAL_STR:
{
return qse_awk_rtx_strtonum (
rtx, 0,
rtx,
QSE_AWK_RTX_STRTONUM_MAKE_OPTION(0, 0),
((qse_awk_val_str_t*)v)->val.ptr,
((qse_awk_val_str_t*)v)->val.len,
l, r
@ -1691,15 +1694,18 @@ int qse_awk_rtx_valtoflt (
}
int qse_awk_rtx_strtonum (
qse_awk_rtx_t* rtx, int strict,
qse_awk_rtx_t* rtx, int option,
const qse_char_t* ptr, qse_size_t len,
qse_awk_int_t* l, qse_awk_flt_t* r)
{
const qse_char_t* endptr;
const qse_char_t* end;
int strict = QSE_AWK_RTX_STRTONUM_GET_OPTION_STRICT(option);
int base = QSE_AWK_RTX_STRTONUN_GET_OPTION_BASE(option);
end = ptr + len;
*l = qse_awk_strxtoint (rtx->awk, ptr, len, 0, &endptr);
*l = qse_awk_strxtoint(rtx->awk, ptr, len, base, &endptr);
if (endptr < end)
{
if (*endptr == QSE_T('.') || *endptr == QSE_T('E') || *endptr == QSE_T('e'))