--- Convert-BER-XS/XS.xs 2019/04/19 19:46:29 1.3 +++ Convert-BER-XS/XS.xs 2019/04/19 20:38:38 1.4 @@ -658,19 +658,28 @@ len_fixup (mark); } -static void -encode_ber (SV *tuple) +// checkl whether an SV is a BER tuple and returns its AV * +static AV * +ber_tuple (SV *tuple) { - if (expect_false (!SvROK (tuple) || SvTYPE (SvRV (tuple)) != SVt_PVAV)) - croak ("BER tuple must be array-reference"); + SV *rv; - AV *av = (AV *)SvRV (tuple); + if (expect_false (!SvROK (tuple) || SvTYPE ((rv = SvRV (tuple))) != SVt_PVAV)) + croak ("BER tuple must be array-reference"); - if (expect_false (SvRMAGICAL (av))) + if (expect_false (SvRMAGICAL (rv))) croak ("BER tuple must not be tied"); - if (expect_false (AvFILL (av) != BER_ARRAYSIZE - 1)) - croak ("BER tuple must contain exactly %d elements, not %d", BER_ARRAYSIZE, AvFILL (av) + 1); + if (expect_false (AvFILL ((AV *)rv) != BER_ARRAYSIZE - 1)) + croak ("BER tuple must contain exactly %d elements, not %d", BER_ARRAYSIZE, AvFILL ((AV *)rv) + 1); + + return (AV *)rv; +} + +static void +encode_ber (SV *tuple) +{ + AV *av = ber_tuple (tuple); int klass = SvIV (AvARRAY (av)[BER_CLASS]); int tag = SvIV (AvARRAY (av)[BER_TAG]); @@ -800,14 +809,13 @@ void ber_is (SV *tuple, SV *klass = &PL_sv_undef, SV *tag = &PL_sv_undef, SV *constructed = &PL_sv_undef, SV *data = &PL_sv_undef) - PROTOTYPE: $;$$$ PPCODE: { if (!SvOK (tuple)) XSRETURN_NO; if (!SvROK (tuple) || SvTYPE (SvRV (tuple)) != SVt_PVAV) - croak ("ber_seq: tuple must be ber tuple (array-ref)"); + croak ("ber_is: tuple must be BER tuple (array-ref)"); AV *av = (AV *)SvRV (tuple); @@ -816,7 +824,7 @@ && (!SvOK (tag) || SvIV (AvARRAY (av)[BER_TAG ]) == SvIV (tag)) && (!SvOK (constructed) || !SvIV (AvARRAY (av)[BER_CONSTRUCTED]) == !SvIV (constructed)) && (!SvOK (data) || sv_eq (AvARRAY (av)[BER_DATA ], data)) - ? &PL_sv_yes : &PL_sv_no); + ? &PL_sv_yes : &PL_sv_undef); } void @@ -826,10 +834,7 @@ if (!SvOK (tuple)) XSRETURN_UNDEF; - if (!SvROK (tuple) || SvTYPE (SvRV (tuple)) != SVt_PVAV) - croak ("ber_seq: tuple must be ber tuple (array-ref)"); - - AV *av = (AV *)SvRV (tuple); + AV *av = ber_tuple (tuple); XPUSHs ( SvIV (AvARRAY (av)[BER_CLASS ]) == ASN_UNIVERSAL @@ -839,43 +844,40 @@ } void -ber_is_i32 (SV *tuple, IV value) +ber_is_i32 (SV *tuple, SV *value = &PL_sv_undef) PPCODE: { if (!SvOK (tuple)) XSRETURN_NO; - if (!SvROK (tuple) || SvTYPE (SvRV (tuple)) != SVt_PVAV) - croak ("ber_seq: tuple must be ber tuple (array-ref)"); + AV *av = ber_tuple (tuple); - AV *av = (AV *)SvRV (tuple); + IV data = SvIV (AvARRAY (av)[BER_DATA]); XPUSHs ( - SvIV (AvARRAY (av)[BER_CLASS ]) == ASN_UNIVERSAL - && SvIV (AvARRAY (av)[BER_TAG ]) == ASN_INTEGER32 - && !SvIV (AvARRAY (av)[BER_CONSTRUCTED]) - && SvIV (AvARRAY (av)[BER_DATA ]) == value - ? &PL_sv_yes : &PL_sv_no); + SvIV (AvARRAY (av)[BER_CLASS ]) == ASN_UNIVERSAL + && SvIV (AvARRAY (av)[BER_TAG ]) == ASN_INTEGER32 + && !SvIV (AvARRAY (av)[BER_CONSTRUCTED]) + && (!SvOK (value) || data == SvIV (value)) + ? sv_2mortal (data ? newSViv (data) : newSVpv ("0 but true", 0)) + : &PL_sv_undef); } void -ber_is_oid (SV *tuple, SV *oid) +ber_is_oid (SV *tuple, SV *oid = &PL_sv_undef) PPCODE: { if (!SvOK (tuple)) XSRETURN_NO; - if (!SvROK (tuple) || SvTYPE (SvRV (tuple)) != SVt_PVAV) - croak ("ber_seq: tuple must be ber tuple (array-ref)"); - - AV *av = (AV *)SvRV (tuple); + AV *av = ber_tuple (tuple); XPUSHs ( SvIV (AvARRAY (av)[BER_CLASS ]) == ASN_UNIVERSAL && SvIV (AvARRAY (av)[BER_TAG ]) == ASN_OBJECT_IDENTIFIER && !SvIV (AvARRAY (av)[BER_CONSTRUCTED]) - && sv_eq (AvARRAY (av)[BER_DATA], oid) - ? &PL_sv_yes : &PL_sv_no); + && (!SvOK (oid) || sv_eq (AvARRAY (av)[BER_DATA], oid)) + ? newSVsv (AvARRAY (av)[BER_DATA]) : &PL_sv_undef); } ############################################################################# @@ -894,3 +896,32 @@ XPUSHs (buf_sv); } +SV * +ber_i32 (IV iv) + CODE: +{ + AV *av = newAV (); + av_fill (av, BER_ARRAYSIZE - 1); + AvARRAY (av)[BER_CLASS ] = newSVcacheint (ASN_UNIVERSAL); + AvARRAY (av)[BER_TAG ] = newSVcacheint (ASN_INTEGER32); + AvARRAY (av)[BER_CONSTRUCTED] = newSVcacheint (0); + AvARRAY (av)[BER_DATA ] = newSViv (iv); + RETVAL = newRV_noinc ((SV *)av); +} + OUTPUT: RETVAL + +# TODO: not arrayref, but elements? +SV * +ber_seq (SV *arrayref) + CODE: +{ + AV *av = newAV (); + av_fill (av, BER_ARRAYSIZE - 1); + AvARRAY (av)[BER_CLASS ] = newSVcacheint (ASN_UNIVERSAL); + AvARRAY (av)[BER_TAG ] = newSVcacheint (ASN_SEQUENCE); + AvARRAY (av)[BER_CONSTRUCTED] = newSVcacheint (1); + AvARRAY (av)[BER_DATA ] = newSVsv (arrayref); + RETVAL = newRV_noinc ((SV *)av); +} + OUTPUT: RETVAL +