Procedure for Calling C Decode Functions

This section describes the step-by-step procedure for calling a C XML decode function. This method must be used if C code generation was done. This method can also be used as an alternative to using the control class interface if C++ code generation was done.

These are the steps involved calling a compiler-generated decode function:

  1. Prepare a context variable for decoding

  2. Open an input stream for the XML document to be decoded

  3. Decode the initial tag value to figure out what type of message was received (optional).

  4. Call the appropriate compiler-generated decode function to decode the message

  5. Free the context after use of the decoded data is complete to free allocated memory structures

Before a C XML decode function can be called, the user must first initialize a context block structure. The context block structure is initialized by calling the rtXmlInitContext function.

An input stream is then opened using one of the rtxStream functions. If the data is to be read from a file, the rtxStreamFileCreateReader function can use used. Similar functions exist for opening a memory or socket-based stream.

If the user knows the type of XML message that is to be processed, he can directly call the decode function at this point. If not, the user may call the rtXmlpMatchStartTag method to match the initial tag in the message with a known start tag. The user can continue to do this until a match is found with one of the expected message types. Note that the rtXmlpMarkLastEvent function must be called if the tag is to be reparsed to attempt another match operation.

A decode function can then be called to decode the message. If the return status indicates success (0), then the message will have been decoded into the given ASN.1 type variable. The decode function may automatically allocate dynamic memory to hold variable length variables during the course of decoding. This memory will be tracked in the context structure, so the programmer does not need to worry about freeing it. It will be released when the context is freed.

The final step of the procedure is to free the context block. The function to free the context is rtFreeContext.

A program fragment that could be used to decode an employee record is as follows:

   #include employee.h            /* include file generated by ASN1C */

   main ()
   {
      PersonnelRecord data;
      OSCTXT ctxt;
      OSBOOL trace = TRUE, verbose = FALSE;
      const char* filename = "message.xml";
      int i, stat;

      .. logic to read message into msgbuf ..

      /* This example uses a static context block */

      /* step 1: initialize the context block */

      stat = rtXmlInitContext (&ctxt);

      if (stat != 0) {
         rtxErrPrint (&ctxt);
         return stat;
      }

      /* step 2: open an input stream */

      stat = rtxStreamFileCreateReader (&ctxt, filename);
      if (stat != 0) {
         rtxErrPrint (&ctxt);
         return -1;
      }

      /* step 3: attempt to match the start tag to a known value */

      if (0 == rtXmlpMatchStartTag (&ctxt, OSUTF8(“Employee”)) {
         /* Note that it is necessary to mark the last event active in
            the pull-parser to that it can be parsed again in the PDU
            decode function. */
         rtXmlpMarkLastEventActive (&ctxt);

         /* step 4: call the decode function */

         stat = XmlDec_PersonnelRecord_PDU (&ctxt, &data);

         if (stat == 0)
         {
            process received data..
         }
         else {
            /* error processing... */
            rtxErrPrint (&ctxt);
         }
      }
      /* can check for other possible tag matches here.. */

      /* step 5: free the context */

      rtFreeContext (&ctxt);
   }