Sample programs can be found in c/sample_uper/rawEvent
and
cpp/sample_uper/rawEvent
. These illustrate the use of a raw event
parser. The writer program creates input data for the reader, and is of no particular
interest. The reader program implements the event handlers.
This code from the component event handler (for the C case) decodes the PDU.record element, and ignores elements that are not on the path to the open type in PDU.values[i].data:
ASN1RawEventResp compEvt (OSCTXT* pctxt, OSSIZE componentID, OSBOOL nestedValues) { ... if (componentID == RAWID_RAWEVENTS_PDU_RECORD) { /* Decode the Record ourselves, and print it. Then tell the parser we've consumed it. */ Record rec; asn1PD_Record(pctxt, &rec); printf("The Record is:\n"); asn1Print_Record("record", &rec); return ASN1RER_CONSUMED; } else if (componentID == RAWID_RAWEVENTS_PDU_VALUES || componentID == RAWID_RAWEVENTS__SEQOFVALUETABLE_ELEMENT || componentID == RAWID_RAWEVENTS_VALUETABLE_DATA) { /* We want to get events for the above elements */ return ASN1RER_PARSE; } else return ASN1RER_QUIET_PARSE; }
This code from the actual-type event handler (for the C case) decodes PDU.values[i].data if the actual type for that component is a Record:
ASN1RawEventResp actualType (OSCTXT* pctxt, OSSIZE actualTypeID, OSSIZE len) { ... /* All branches here return ASN1RER_CONSUMED or ASN1RER_QUIET_PARSE, so we won't receive an end component event. */ if (actualTypeID == 0) { printf("Actual type event for unknown type" " having length of " OSSIZEFMT "\n", len); return ASN1RER_QUIET_PARSE; } else if (actualTypeID == RAWID_RAWEVENTS_VALUETABLE_DATA_T_RECORD) { /* Open type's actual type is Record. Decode it ourselves, and print it. Then tell the parser we've consumed it. */ Record rec; asn1PD_Record(pctxt, &rec); printf("Open type is Record:\n"); asn1Print_Record("record", &rec); return ASN1RER_CONSUMED; } else { printf("Actual type event for " OSSIZEFMT " having length of " OSSIZEFMT "\n", actualTypeID, len); return ASN1RER_QUIET_PARSE; } }
For C++, the code would be very similar, except it will appear in your subclass
implementation of Asn1RawEventHandler
.
For C, you can use OSCTXT.pUserData
to
hold an object for maintaining state between calls to your event
handlers. You could do the same for C++, but your subclass implementation
of Asn1RawEventHandler
is probably more convenient.
Finally, here is how the event handler is set up for C (from the C sample program):
#include "rtsrc/asn1CRawEvtHndlr.h" ... int main (int argc, char** argv) { OSCTXT ctxt; Asn1CRawEventHandler handler; /* My state-tracking object */ EvtTrack track; ... /* Set the function pointers to my implementation of the event handlers */ handler.component = compEvt; handler.endComponent = endCompEvt; handler.actualType = actualType; ... /* Add my handler to the context */ rtAddRawEventHandler(&ctxt, &handler); /* Store my state-tracking object in the context */ ctxt.pUserData = &track; /* Call compiler generated parse function */ stat = asn1PP_PDU (&ctxt, ASN1RER_PARSE); if (stat != 0) { printf ("decode of data failed\n"); rtxErrPrint (&ctxt); rtFreeContext (&ctxt); return -1; } ...
And, here is how the event handler is set up for C++ (from the C++ sample program):
#include "rtsrc/asn1CppRawEvtHndlr.h" ... int main (int argc, char** argv) { ... ASN1PERDecodeBuffer decodeBuffer (aligned); decodeBuffer.setRunTimeKey(_rtkey, sizeof(_rtkey)); ... /* My subclass of Asn1RawEventHandler */ SampleHandler handler; /* Add the event handler to the decode buffer's context. */ handler.addEventHandler(decodeBuffer); /* Call the compiler-generated raw parser function. */ stat = asn1PP_PDU(decodeBuffer.getCtxtPtr(), ASN1RER_PARSE); if (stat != 0) { printf ("decode failed\n"); decodeBuffer.PrintErrorInfo (); return stat; }