--- Net-SNMP-XS/XS.xs 2009/04/09 07:10:23 1.7 +++ Net-SNMP-XS/XS.xs 2009/04/11 06:24:18 1.10 @@ -4,7 +4,7 @@ // C99 required -#define BENCHMARK +//#define BENCHMARK #define ASN_BOOLEAN 0x01 #define ASN_INTEGER32 0x02 @@ -21,6 +21,8 @@ #define MAX_OID_STRLEN 4096 +#define HAVE_VERSIONSORT defined (_GNU_SOURCE) && __GLIBC__ >= 2 && __GLIBC_MINOR__ >= 1 + static SV *msg; static int errflag, leading_dot; static U8 *buf, *cur; @@ -40,11 +42,20 @@ } static void -error (const char *msg) +error (const char *errmsg) { errflag = 1; - printf ("<<<%s>>>\n", msg);//D + if (!msg) + croak ("Net::SNMP::XS fatal error, parser called without parsing context"); + + dSP; + PUSHMARK (SP); + EXTEND (SP, 2); + PUSHs (msg); + PUSHs (sv_2mortal (newSVpv (errmsg, 0))); + PUTBACK; + call_method ("_error", G_VOID | G_DISCARD); } static int @@ -185,6 +196,52 @@ return newSVuv ((U32)process_integer32 ()); } +#if IVSIZE >= 8 + +static U64TYPE +process_integer64 (void) +{ + U32 length = process_length (); + + if (length <= 0) + { + error ("INTEGER64 length equal to zero"); + return 0; + } + + U8 *data = getn (length, 0); + + if (!data) + return 0; + + if (length > 9 || (length > 8 && data [0])) + { + error ("INTEGER64 length too long"); + return 0; + } + + U64TYPE res = data [0] & 0x80 ? 0xffffffffffffffff : 0; + + while (length--) + res = (res << 8) | *data++; + + return res; +} + +static SV * +process_integer64_sv (void) +{ + return newSViv ((I64TYPE)process_integer64 ()); +} + +static SV * +process_unsigned64_sv (void) +{ + return newSVuv ((U64TYPE)process_integer64 ()); +} + +#endif + static SV * process_octet_string_sv (void) { @@ -220,7 +277,7 @@ if (length <= 0) { error ("OBJECT IDENTIFIER length equal to zero"); - return ""; + return &PL_sv_undef; } U8 *end = cur + length; @@ -304,6 +361,24 @@ return errflag ? &PL_sv_undef : res; } +///////////////////////////////////////////////////////////////////////////// + +#if HAVE_VERSIONSORT + +static int +oid_lex_cmp (const void *a_, const void *b_) +{ + const char *a = SvPVX (*(SV **)a_); + const char *b = SvPVX (*(SV **)b_); + + a += *a == '.'; + b += *b == '.'; + + return strverscmp (a, b); +} + +#endif + MODULE = Net::SNMP::XS PACKAGE = Net::SNMP::XS PROTOTYPES: ENABLE @@ -319,6 +394,10 @@ void set_msg (SV *msg_, SV *buf_) CODE: +{ + if (msg) + croak ("recursive invocation of Net::SNMP::XS parser is not supported"); + errflag = 0; leading_dot = -1; msg = SvREFCNT_inc (msg_); @@ -328,12 +407,13 @@ #ifdef BENCHMARK t1 = tstamp (); #endif +} void clr_msg () CODE: - SvREFCNT_dec (msg); - buf = cur = ""; + SvREFCNT_dec (msg); msg = 0; + buf = cur = (U8 *)""; len = rem = 0; #ifdef BENCHMARK printf ("%f\n", tstamp () - t1);//D @@ -403,6 +483,17 @@ OUTPUT: RETVAL +#if IVSIZE >= 8 + +SV * +_process_counter64 (SV *self, ...) + CODE: + RETVAL = process_unsigned64_sv (); + OUTPUT: + RETVAL + +#endif + SV * _process_object_identifier (SV *self, ...) CODE: @@ -497,4 +588,69 @@ OUTPUT: RETVAL +MODULE = Net::SNMP::XS PACKAGE = Net::SNMP + +void +oid_base_match (SV *base_, SV *oid_) + PROTOTYPE: $$ + ALIAS: + oid_context_match = 0 + PPCODE: +{ + if (!SvOK (base_) || !SvOK (oid_)) + XSRETURN_NO; + + STRLEN blen, olen; + char *base = SvPV (base_, blen); + char *oid = SvPV (oid_ , olen); + + blen -= *base == '.'; base += *base == '.'; + olen -= *base == '.'; oid += *oid == '.'; + + if (olen < blen) + XSRETURN_NO; + + if (memcmp (base, oid, blen)) + XSRETURN_NO; + + if (oid [blen] && oid [blen] != '.') + XSRETURN_NO; + + XSRETURN_YES; +} + +#if HAVE_VERSIONSORT + +void +oid_lex_sort (...) + PROTOTYPE: @ + PPCODE: +{ + // make sure SvPVX is valid + int i; + for (i = items; i--; ) + { + SV *sv = ST (i); + + if (SvTYPE (sv) < SVt_PV || SvTYPE (sv) == SVt_PVAV && SvTYPE (sv) == SVt_PVHV) + SvPV_force_nolen (sv); + } + + qsort (&ST (0), items, sizeof (SV *), oid_lex_cmp); + + EXTEND (SP, items); + // we cheat somewhat by not returning copies here + for (i = 0; i < items; ++i) + PUSHs (sv_2mortal (SvREFCNT_inc (ST (i)))); +} + +int +_index_cmp (const char *a, const char *b) + PROTOTYPE: $$ + CODE: + RETVAL = strverscmp (a, b); + OUTPUT: + RETVAL + +#endif