diff options
Diffstat (limited to 'Util.xs')
-rw-r--r-- | Util.xs | 369 |
1 files changed, 369 insertions, 0 deletions
@@ -0,0 +1,369 @@ +#include "EXTERN.h" +#include "perl.h" +#include "XSUB.h" + +/* Changes in 5.7 series mean that now IOK is only set if scalar is + precisely integer but in 5.6 and earlier we need to do a more + complex test */ +#if PERL_VERSION <= 6 +#define DD_is_integer(sv) (SvIOK(sv) && (SvIsUV(val) ? SvUV(sv) == SvNV(sv) : SvIV(sv) == SvNV(sv))) +#else +#define DD_is_integer(sv) SvIOK(sv) +#endif + +static int +is_string0( SV *sv ) +{ + return SvFLAGS(sv) & (SVf_OK & ~SVf_ROK); +} + +static int +is_string( SV *sv ) +{ + STRLEN len = 0; + if( is_string0(sv) ) + { + const char *pv = SvPV(sv, len); + } + return len; +} + +static int +is_array( SV *sv ) +{ + return SvROK(sv) && ( SVt_PVAV == SvTYPE(SvRV(sv) ) ); +} + +static int +is_hash( SV *sv ) +{ + return SvROK(sv) && ( SVt_PVHV == SvTYPE(SvRV(sv) ) ); +} + +static int +is_like( SV *sv, const char *like ) +{ + int likely = 0; + if( sv_isobject( sv ) ) + { + dSP; + int count; + + ENTER; + SAVETMPS; + PUSHMARK(SP); + XPUSHs( sv_2mortal( newSVsv( sv ) ) ); + XPUSHs( sv_2mortal( newSVpv( like, strlen(like) ) ) ); + PUTBACK; + + if( ( count = call_pv("overload::Method", G_SCALAR) ) ) + { + I32 ax; + SPAGAIN; + + SP -= count; + ax = (SP - PL_stack_base) + 1; + if( SvTRUE(ST(0)) ) + ++likely; + } + + PUTBACK; + FREETMPS; + LEAVE; + } + + return likely; +} + +MODULE = Params::Util PACKAGE = Params::Util + +void +_STRING(sv) + SV *sv +PROTOTYPE: $ +CODE: +{ + if( SvMAGICAL(sv) ) + mg_get(sv); + if( is_string( sv ) ) + { + ST(0) = sv; + XSRETURN(1); + } + XSRETURN_UNDEF; +} + +void +_NUMBER(sv) + SV *sv; +PROTOTYPE: $ +CODE: +{ + if( SvMAGICAL(sv) ) + mg_get(sv); + if( ( SvIOK(sv) ) || ( SvNOK(sv) ) || ( is_string( sv ) && looks_like_number( sv ) ) ) + { + ST(0) = sv; + XSRETURN(1); + } + XSRETURN_UNDEF; +} + +void +_SCALAR0(ref) + SV *ref; +PROTOTYPE: $ +CODE: +{ + if( SvMAGICAL(ref) ) + mg_get(ref); + if( SvROK(ref) ) + { + if( ( SvTYPE(SvRV(ref)) <= SVt_PVBM ) && !sv_isobject(ref) ) + { + ST(0) = ref; + XSRETURN(1); + } + } + XSRETURN_UNDEF; +} + +void +_SCALAR(ref) + SV *ref; +PROTOTYPE: $ +CODE: +{ + if( SvMAGICAL(ref) ) + mg_get(ref); + if( SvROK(ref) ) + { + svtype tp = SvTYPE(SvRV(ref)); + if( ( SvTYPE(SvRV(ref)) <= SVt_PVBM ) && (!sv_isobject(ref)) && is_string( SvRV(ref) ) ) + { + ST(0) = ref; + XSRETURN(1); + } + } + XSRETURN_UNDEF; +} + +void +_REGEX(ref) + SV *ref; +PROTOTYPE: $ +CODE: +{ + if( SvMAGICAL(ref) ) + mg_get(ref); + if( SvROK(ref) ) + { + svtype tp = SvTYPE(SvRV(ref)); +#if PERL_VERSION >= 11 + if( ( SVt_REGEXP == tp ) ) +#else + if( ( SVt_PVMG == tp ) && sv_isobject(ref) + && ( 0 == strncmp( "Regexp", sv_reftype(SvRV(ref),TRUE), + strlen("Regexp") ) ) ) +#endif + { + ST(0) = ref; + XSRETURN(1); + } + } + XSRETURN_UNDEF; +} + +void +_ARRAY0(ref) + SV *ref; +PROTOTYPE: $ +CODE: +{ + if( SvMAGICAL(ref) ) + mg_get(ref); + if( is_array(ref) ) + { + ST(0) = ref; + XSRETURN(1); + } + + XSRETURN_UNDEF; +} + +void +_ARRAY(ref) + SV *ref; +PROTOTYPE: $ +CODE: +{ + if( SvMAGICAL(ref) ) + mg_get(ref); + if( is_array(ref) && ( av_len((AV *)(SvRV(ref))) >= 0 ) ) + { + ST(0) = ref; + XSRETURN(1); + } + XSRETURN_UNDEF; +} + +void +_ARRAYLIKE(ref) + SV *ref; +PROTOTYPE: $ +CODE: +{ + if( SvMAGICAL(ref) ) + mg_get(ref); + if( SvROK(ref) ) + { + if( is_array(ref) || is_like( ref, "@{}" ) ) + { + ST(0) = ref; + XSRETURN(1); + } + } + + XSRETURN_UNDEF; +} + +void +_HASH0(ref) + SV *ref; +PROTOTYPE: $ +CODE: +{ + if( SvMAGICAL(ref) ) + mg_get(ref); + if( is_hash(ref) ) + { + ST(0) = ref; + XSRETURN(1); + } + + XSRETURN_UNDEF; +} + +void +_HASH(ref) + SV *ref; +PROTOTYPE: $ +CODE: +{ + if( SvMAGICAL(ref) ) + mg_get(ref); + if( is_hash(ref) && ( HvKEYS(SvRV(ref)) >= 1 ) ) + { + ST(0) = ref; + XSRETURN(1); + } + + XSRETURN_UNDEF; +} + +void +_HASHLIKE(ref) + SV *ref; +PROTOTYPE: $ +CODE: +{ + if( SvMAGICAL(ref) ) + mg_get(ref); + if( SvROK(ref) ) + { + if( is_hash(ref) || is_like( ref, "%{}" ) ) + { + ST(0) = ref; + XSRETURN(1); + } + } + + XSRETURN_UNDEF; +} + +void +_CODE(ref) + SV *ref; +PROTOTYPE: $ +CODE: +{ + if( SvMAGICAL(ref) ) + mg_get(ref); + if( SvROK(ref) ) + { + if( SVt_PVCV == SvTYPE(SvRV(ref)) ) + { + ST(0) = ref; + XSRETURN(1); + } + } + XSRETURN_UNDEF; +} + +void +_CODELIKE(ref) + SV *ref; +PROTOTYPE: $ +CODE: +{ + if( SvMAGICAL(ref) ) + mg_get(ref); + if( SvROK(ref) ) + { + if( ( SVt_PVCV == SvTYPE(SvRV(ref)) ) || ( is_like(ref, "&{}" ) ) ) + { + ST(0) = ref; + XSRETURN(1); + } + } + XSRETURN_UNDEF; +} + +void +_INSTANCE(ref,type) + SV *ref; + char *type; +PROTOTYPE: $$ +CODE: +{ + STRLEN len; + if( SvMAGICAL(ref) ) + mg_get(ref); + if( SvROK(ref) && type && ( ( len = strlen(type) ) > 0 ) ) + { + if( sv_isobject(ref) ) + { + I32 isa_type = 0; + int count; + + ENTER; + SAVETMPS; + PUSHMARK(SP); + XPUSHs( sv_2mortal( newSVsv( ref ) ) ); + XPUSHs( sv_2mortal( newSVpv( type, len ) ) ); + PUTBACK; + + if( ( count = call_method("isa", G_SCALAR) ) ) + { + I32 oldax = ax; + SPAGAIN; + SP -= count; + ax = (SP - PL_stack_base) + 1; + isa_type = SvTRUE(ST(0)); + ax = oldax; + } + + PUTBACK; + FREETMPS; + LEAVE; + + if( isa_type ) + { + ST(0) = ref; + XSRETURN(1); + } + } + } + XSRETURN_UNDEF; +} + |