Procedure for Calling a Generated C Encode Function

The encode function generated for an XSD global element definition is the normal entry point for encoding a JSON message. The general procedure for calling a global element encode function is as follows:

  1. Prepare a context variable for encoding

  2. Initialize an encode message buffer or stream to receive the encoded data

  3. Populate the data variable with data to be encoded

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

  5. If a message buffer was used, get the start pointer and length of the encoded message

Before a C JSON encode function can be called; the user must initialize a context variable. This is a variable of type OSCTXT. This variable holds all of the working data used during the encoding of a message. The context variable is declared as a normal automatic variable within the top-level calling function. It must be initialized before use. This can be accomplished by using the rtxInitContext function:

       OSCTXT ctxt;/* context variable */
       stat = rtxInitContext (&ctxt);
       if (0 != stat) {
          printf ("Context initialization failed.\n");
          rtxErrPrint (&ctxt);
          return stat;
       }

The next step is to specify an encode buffer or stream into which the message will be encoded. This is accomplished by calling the rtxInitContextBuffer run-time function (for a message buffer) or one of the rtxStream functions to create an output stream. If a message buffer is to be used, the user has the option to either pass the address of a buffer and size allocated in his or her program (referred to as a static buffer), or set these parameters to zero and let the encode function manage the buffer memory allocation (referred to as a dynamic buffer). Better performance can normally be attained by using a static buffer because this eliminates the high-overhead operation of allocating and reallocating memory.

After initializing the context and populating a variable of the structure to be encoded, an encode function can be called to encode the message. If the return status indicates success, the run-time library function rtxCtxtGetMsgPtr can be called to obtain the start address of the encoded message. In the static case, this is simply the start address of the static buffer. In the dynamic case, this function will return the pointer to the allocated memory buffer. The memory allocated for a dynamic buffer will be freed when either the context is freed (rtxFreeContext) or all memory associated with the context is released (rtxMemFree) or the buffer memory is explicity released (rtxMemFreePtr).

In the stream case, the pointer to the encoded message generally cannot be obtained since the message has already been written to the stream. The stream should be closed after encoding is complete by calling the rtxStreamClose function. This should be called before calling the rtxFreeContext function.

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

   #include "employee.h"

   #define MAXMSGLEN 1024

   int main (int argc, char** argv)
   {
      PersonnelRecord employee;
      OSCTXT ctxt;
      OSOCTET msgbuf[MAXMSGLEN];
      int stat;

      /* Init context */

      stat = rtxInitContext (&ctxt);
      if (0 != stat) {
         printf ("Context initialization failed.\n");
         rtxErrPrint (&ctxt);
         return stat;
      }

      /* Populate structure of generated type */

      Init_PersonnelRecord (&ctxt, &employee);

      ... logic to populate structure here ...

      /* Encode */

      stat = rtxInitContextBuffer (&ctxt, msgbuf, sizeof(msgbuf));

      if (0 == stat)
         stat = JsonEnc_personnelRecord (&ctxt, &employee);

      if (0 == stat) {
         printf ("encoded message:\n");
         printf (msgbuf);
         printf ("\n");
      }
      else {
         printf ("Encoding failed\n");
         rtxErrPrint (&ctxt);
         return stat;
      }

         ... logic to process encoded message (write to file, etc.) ...
   
      rtxFreeContext (&ctxt);

This example uses a static message buffer. The encoded XML text will reside in the msgbuf message buffer after the procedure is complete.

A program fragment that could be used to encode an employee record to a file stream is as follows:

    #include "rtxsrc/rtxStreamFile.h"
    #include "employee.h"

    int main (int argc, char** argv)
    {
       PersonnelRecord employee;
       OSCTXT ctxt;
       int stat;
       const char* filename = "message.json";

       /* Init context */

       stat = rtxInitContext (&ctxt);
       if (0 != stat) {
          printf ("Context initialization failed.\n");
          rtxErrPrint (&ctxt);
          return stat;
       }

       /* Populate structure of generated type */

       Init_PersonnelRecord (&ctxt, &employee);

       ... logic to populate structure here ...

       /* Encode directly to output stream */

       stat = rtxStreamFileCreateWriter (&ctxt, filename);
       if (0 != stat) {
          printf ("Stream initialization failed.\n");
          rtxErrPrint (&ctxt);
          return stat;
       }

       stat = JsonEnc_personnelRecord (&ctxt, &employee);

       if (0 != stat) {
          printf ("Encoding failed\n");
          rtxErrPrint (&ctxt);
          return stat;
       }
       rtxStreamClose (&ctxt);
       rtxFreeContext (&ctxt);
       return 0;
    }