Permalink
Find file
Fetching contributors…
Cannot retrieve contributors at this time
188 lines (157 sloc) 4.59 KB
#define PERL_NO_GET_CONTEXT
#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"
#include "ppport.h"
STATIC I32 is_num(pTHX_ SV * sv);
STATIC I32 is_num(pTHX_ SV * sv) {
I32 type = 0;
if (sv && SvOK(sv)) {
STRLEN len;
const char * str = NULL;
if (SvPOK(sv)) {
str = SvPVX_const(sv);
len = SvCUR(sv);
} else { /* stringify numbers, references and overloaded objects */
str = SvPV_const(sv, len);
}
/*
* handle 1.#INF (Inf), -1.#INF (-Inf), and 1.#IND (NaN) on Windows:
* http://www.johndcook.com/IEEE_exceptions_in_cpp.html
* https://rt.perl.org/Public/Bug/Display.html?id=122843
*
* switch-trie generated by Devel::Tokenizer::C (Marcus Holland-Moritz++)
* hacked about to make the formatting less annoying :-)
*/
#ifdef WIN32
switch (len) {
case 6: /* 2 tokens of length 6 */
switch (str[5]) {
case 'D':
case 'd':
if (str[0] == '1' &&
str[1] == '.' &&
str[2] == '#' &&
(str[3] == 'I' || str[3] == 'i') &&
(str[4] == 'N' || str[4] == 'n'))
{ /* 1.#IND */
return IS_NUMBER_NAN | IS_NUMBER_NOT_INT;
}
goto fail_early;
case 'F':
case 'f':
if (str[0] == '1' &&
str[1] == '.' &&
str[2] == '#' &&
(str[3] == 'I' || str[3] == 'i') &&
(str[4] == 'N' || str[4] == 'n'))
{ /* 1.#INF */
return IS_NUMBER_INFINITY | IS_NUMBER_NOT_INT;
}
goto fail_early;
default:
goto not_nan_or_inf;
}
case 7: /* 2 tokens of length 7 */
switch (str[6]) {
case 'D':
case 'd':
if (str[0] == '-' &&
str[1] == '1' &&
str[2] == '.' &&
str[3] == '#' &&
(str[4] == 'I' || str[4] == 'i') &&
(str[5] == 'N' || str[5] == 'n'))
{ /* -1.#IND */
return IS_NUMBER_NEG | IS_NUMBER_NAN | IS_NUMBER_NOT_INT;
}
goto fail_early;
case 'F':
case 'f':
if (str[0] == '-' &&
str[1] == '1' &&
str[2] == '.' &&
str[3] == '#' &&
(str[4] == 'I' || str[4] == 'i') &&
(str[5] == 'N' || str[5] == 'n'))
{ /* -1.#INF */
return IS_NUMBER_NEG | IS_NUMBER_INFINITY | IS_NUMBER_NOT_INT;
}
goto fail_early;
default:
goto not_nan_or_inf;
}
default:
goto not_nan_or_inf;
}
fail_early:
return 0;
not_nan_or_inf:
#endif
type = grok_number(str, len, NULL);
}
return type;
}
MODULE = Scalar::Util::Numeric PACKAGE = Scalar::Util::Numeric
void
uvmax()
PROTOTYPE:
CODE:
XSRETURN_UV(UV_MAX);
void
isnum(sv)
SV * sv
PROTOTYPE: $
CODE:
XSRETURN_IV(is_num(aTHX_ sv));
void
isint(sv)
SV * sv
PROTOTYPE: $
CODE:
I32 type = is_num(aTHX_ sv);
I32 ret;
if (type == 1) {
ret = 1;
} else if (type == 9) {
ret = -1;
} else {
ret = -0;
}
XSRETURN_IV(ret);
void
isuv(sv)
SV * sv
PROTOTYPE: $
CODE:
XSRETURN_IV((is_num(aTHX_ sv) & 1) ? 1 : 0);
void
isbig(sv)
SV * sv
PROTOTYPE: $
CODE:
XSRETURN_IV((is_num(aTHX_ sv) & 2) ? 1 : 0);
void
isfloat(sv)
SV * sv
PROTOTYPE: $
CODE:
XSRETURN_IV((is_num(aTHX_ sv) & 4) ? 1 : 0);
void
isneg(sv)
SV * sv
PROTOTYPE: $
CODE:
XSRETURN_IV((is_num(aTHX_ sv) & 8) ? 1 : 0);
void
isinf(sv)
SV * sv
PROTOTYPE: $
CODE:
XSRETURN_IV((is_num(aTHX_ sv) & 16) ? 1 : 0);
void
isnan(sv)
SV * sv
PROTOTYPE: $
CODE:
XSRETURN_IV((is_num(aTHX_ sv) & 32) ? 1 : 0);