The following sample application illustrates the use of the OSS ASN.1/C++ Compiler to compile a simple ASN.1 module, and the use of the OSS C++ runtime APIs to encode and decode data using ASN.1 binary and text encoding rules.

The C++ application program in this example is tbcas.cpp and the associated ASN.1 source file is bcas.asn . The ASN.1 file contains a value notation "mycard".  The application program shows how this value notation can be encoded using various ASN.1 encoding rules, and then decodes encoded data into C++ objects.

The following steps show how you can create and run a sample executable program using OSS ASN.1/C++ tools.

Step 1: Invoking the ASN.1 Compiler

1.1 Input ASN.1 Syntax (bcas.asn)
1.2 Command to compile bcas.asn
1.3 Output files generated by the ASN.1 Compiler

Step 2:  Compiling and Linking the sample application

2.1 Input application program tbcas.cpp
2.2 Commands to compile and link the sample program

Step 3: Running the sample program

3.1 Command to run the executable
3.2 Output of the sample program


Step 1: Invoking the ASN.1 Compiler

The following describes how to compile abstract syntax defined in the bcas.asn file.

1.1 Input ASN.1 Syntax (bcas.asn)

BCAS DEFINITIONS ::= BEGIN

        BBCard ::= SEQUENCE {
                name IA5String (SIZE (1..60)),
                team IA5String (SIZE (1..60)),
                age INTEGER (1..100),
                position IA5String (SIZE (1..60)),
                handedness ENUMERATED
                        {left-handed(0), right-handed(1), ambidextrous(2)},
                batting-average REAL --<DECIMAL>--
        }

        myCard BBCard ::= {
                name "Casey",
                team "Mudville Nine",
                age 32,
                position "left field",
                handedness ambidextrous,
                batting-average {mantissa 250, base 10, exponent -3}
        }

END

Go back to top

1.2 Command to compile bcas.asn

The following command compiles bcas.asn, and generates the bcas.h and bcas.cpp files. The bcas.h file contains the classes corresponding to the components of ASN.1 file. The bcas.cpp file contains information needed by the encoder and the decoder at the runtime. The file, bcas.cpp ,  must be compiled and linked with the sample application.

asn1cpp -per -ber -xer bcas.asn

or

asn1cpp -per -ber -xer bcas

The -ber, -per and -xer compiler options notify the compiler that BER (Basic Encoding Rules), PER (Packed Encoding Rules) and XER (XML Encoding Rules) will be used at runtime. Detailed description of all the compiler options supported by the OSS ASN.1/C++ Compiler can be found in the OSS ASN.1 Compiler for C++ Reference Manual .

Go back to top

1.3 Output files generated by the ASN.1 Compiler

bcas.h

#ifndef OSS_bcas
#define OSS_bcas

#include "oss.h"
#include "asn1.h"

/* Representation types */
enum _enum1 {
    left_handed = 0,
    right_handed = 1,
    ambidextrous = 2
};

class OSS_PUBLIC BBCard   /* SEQUENCE */
{
public:
    void * operator new(size_t size);
    void operator delete(void *ptr);

    typedef OssString name;
    typedef OssString team;
    typedef OSS_UINT32 age;
    typedef OssString position;
    typedef enum _enum1 handedness;
    typedef OssDecimal batting_average;

    BBCard();
    BBCard(const BBCard &);
    BBCard(const name &, const team &, age, const position &, handedness, const
batting_average &);

    BBCard & operator = (const BBCard &);
    int operator == (const BBCard &) const;
    int operator != (const BBCard &) const;   

    name& get_name();
    const name& get_name() const;
    void set_name(const name & );

    team& get_team();
    const team& get_team() const;
    void set_team(const team & );

    age& get_age();
    age get_age() const;
    void set_age(age );

    position& get_position();
    const position& get_position() const;
    void set_position(const position & );

    handedness& get_handedness();
    handedness get_handedness() const;
    void set_handedness(handedness );

    batting_average& get_batting_average();
    const batting_average& get_batting_average() const;
    void set_batting_average(const batting_average & );

private:
    name name_field;
    team team_field;
    age age_field;
    position position_field;
    handedness handedness_field;
    batting_average batting_average_field;
};

/* Universal PDU class */

class OSS_PUBLIC bcas_PDU : public UniversalPDU {
public:
    bcas_PDU( );
    void set_BBCard(BBCard &);
    BBCard *get_BBCard( ) const;
};

/* Specific PDU classes */
class OSS_PUBLIC BBCard_PDU : public ConcretePDU {
public:
    BBCard_PDU( );
    void set_data(BBCard &);
    BBCard * get_data() const;
protected:
    OssTypeIndex get_index( ) const;
};

/* Control object class */

class OSS_PUBLIC bcas_Control : public OssControl {
public:
    bcas_Control();
    bcas_Control(const bcas_Control &);
};

/* External definitions for named values */

extern OSS_PUBLIC const BBCard& myCard;

#endif // OSS_bcas

Go back to top

bcas.cpp

The bcas.cpp file contains the information needed by the runtime APIs to encode and decode PDUs. Since this file contains internal information, it is not shown here. This file must be compiled and linked with the sample application.

Step 2:  Compiling and Linking the sample application

The following C++ program, tbcas.cpp , encodes the PDU described by the bcas.asn abstract syntax using BER (Basic Encoding Rules), and then decodes it. Similarly, other encoding rules can be used instead of BER by changing the encoding rule parameter of the ctl.setEncodingRules() method call. For instance, OSS_PER_ALIGNED or OSS_PER_UNALIGNED can be passed for Packed Encoding Rules (PER), or OSS_XER can be passed in order to use Basic XML Encoding Rules (Basic-XER).

Note that bcas.h (generated by the compiler) has been #included in the application program. This header file contains the generated declarations for the application. (The function calls to the OSS Encoder/Decoder functions are in bold font.)

After the application program is compiled, the OSS Encoder/Decoder runtime library must be linked into the resulting executable file.

2.1 Input application program tbcas.cpp

/***************************************************************************
  * Application Program: tbcas.cpp
  * Encodes and decodes a sample baseball card
  * using BCAS (Baseball Card Abstract Syntax)
  */

#include <stdio.h>
#include "bcas.h"

void printStr (OssString&);    /* function for printing    *
                  * non-PDU OssString object */

/* Encodes a card.  If the card is successfully encoded, decodes it. */

int main ()
{
    /* Create control table object and check the result of this operation */
    asn1_clean_error();
    bcas_Control ctl;
    if (asn1_get_last_error()) {
        printf("OssControl object was not created. "
                "Error code is: %d\n", asn1_get_last_error());
        return 1;
    }

    BBCard_PDU pdu;            /* PDU object for data */
    BBCard_PDU pduDecoded;        /* PDU object for decoded data */
    int rc;

    /* Set encoding rules to be used for encoding and decoding
     * Use OSS_PER_ALIGNED for aligned PER, OSS_PER_UNALIGNED for
     * unaligned PER, OSS_CER for CER, OSS_DER for DER, and OSS_XER
     * for Basic-XER.
     */
    ctl.setDecodingFlags(OSS_BER);

    bool isXER = (ctl.getEncodingRules() == OSS_XER);

    /* Enable debugging for both encoder and decoder */
    ctl.setEncodingFlags(DEBUGPDU);
    ctl.setDecodingFlags(DEBUGPDU);

    /* Create a copy of value notation */
    BBCard myCard_copy(myCard);

    /* Set PDU object in this value */
    pdu.set_data(myCard_copy);

    /* Print the input to the encoder */
    printf("\nThe input to the encoder ...\n\n");
    pdu.print(ctl);

    EncodedBuffer encodedData;        /* a buffer for encoded data */

    /* Encode a card. */

    if (!isXER)
    printf("\nThe encoder's trace messages ...\n");
    printf("\n");

if (rc = pdu.encode(ctl, encodedData)) {
    /* an error occurred, print errmsg */
    printf("%s\n", ctl.getErrorMsg());
    return 1;
    } else
    printf("Card encoded.\n");    /* card was successfully encoded */

    /* Get value and length of encoded data and print as hexadecimal string */
    printf("The encoded data is:\n");
    if (!isXER)
        ctl.printHex(encodedData.get_data(), encodedData.get_data_size());
    else
        printf("\n%.*s\n", encodedData.get_data_size(), encodedData.get_data());

    /* Decode a card whose encoding is in encodedData.  Return non-zero
     * for failure. */

    if (!isXER)
    printf("\nThe decoder's trace messages ...\n");
    printf("\n");

if (pduDecoded.decode(ctl, encodedData)) {
    /* an error occurred, print errmsg */
    printf("%s\n", ctl.getErrorMsg());
    return 1;
    } else
    printf("Card decoded.\n");    /* card was successfully decoded */

    /* Get data from PDU object */
    BBCard *myCardPtr = pduDecoded.get_data();    /* address of decoded data */

    /* Print out the player's batting average. */
    printStr(myCardPtr->get_name());
    printf(" of the ");
    printStr(myCardPtr->get_team());
    printf(" has a batting average of %s",
        myCardPtr->get_batting_average().get_value());

    /* Print the decoder's output */
    printf("\nOutput from the decoder ...\n\n");
    pduDecoded.print(ctl);

    /* Create the new card */
    BBCard myFutureCard(*myCardPtr);
    delete myCardPtr;   

    /* Change some fields */
    myFutureCard.set_team(BBCard::team("Mudville Ten"));
    myFutureCard.set_age(BBCard::age(33));
    myFutureCard.set_batting_average(BBCard::batting_average("0.26"));

    printf("\nChanged card is the input to the encoder ... \n");

    /* print the results */
    pdu.set_data(myFutureCard);
    pdu.print(ctl);

    /* Encode a card. */

    if (!isXER)
    printf("\nThe encoder's trace messages ...\n");
    printf("\n");

if (pdu.encode(ctl, encodedData)) {
    printf("%s\n", ctl.getErrorMsg());
    return 1;
    } else
    printf("Card encoded.\n");

    printf("The encoded data is:\n");
    if (!isXER)
        ctl.printHex(encodedData.get_data(), encodedData.get_data_size());
    else
        printf("\n%.*s\n", encodedData.get_data_size(), encodedData.get_data());

    /* Decode a card whose encoding is in encodedData. */

    if (!isXER)
        printf("\nThe decoder's trace messages ...\n");
    printf("\n");

if (pduDecoded.decode(ctl, encodedData)) {
    printf("%s\n", ctl.getErrorMsg());
    return 1;
    } else
    printf("Card decoded.\n");

    /* Create object for encoded data and copy there data from PDU object */
    BBCard myOtherCard = *pduDecoded.get_data();

    /* Print out the player's batting average. */
    printStr(myOtherCard.get_name());
    printf(" of the ");
    printStr(myOtherCard.get_team());
    printf(" has a batting average of %s",
        myOtherCard.get_batting_average().get_value());

    /* Print the decoder's output */
    printf("\nOutput from the decoder ...\n\n");
    pduDecoded.print(ctl);

    /* Free memory allocated for storing representation object in PDU */
    delete pduDecoded.get_data();

    return 0;
}

void printStr (OssString& str)
{
    for(unsigned i = 0; i < str.length(); i++)
    printf("%c", str[i]);           
}
Go back to top

2.2 Command to compile and link sample program

The sample program can be compiled and linked using makefiles asn1cpl.mak and tbcas.mak . The asn1cpl.mak file compiles ASN.1 syntax and generates .h and .cpp files. Another makefile, tbcas.mak, compiles application code, generated .cpp file, and link the object files with OSS runtime libraries to generate sample executable. These makefiles are located under the samples/bcas directory. For example, if you have installed OSS ASN.1/C++ tools under /asn1cpp directory, these makefiles can be found under /asn1cpp/samples/bcas directory. An executable for the sample program can be created by using following commands on Windows and UNIX:

For Windows:
nmake -f asn1cpl.mak
nmake -f tbcas.mak

For Unix:
make -f asn1cpl.mak
make -f tbcas.mak

Go back to top

Step 3: Running the sample program

3.1 Command to run  the executable

An executable tbcas ( tbcas.exe for Windows) will be generated after step 2.2. This executable can be run on the command line by following command:

tbcas

3.2 Output of the sample program

Running tbcas will generate the following output:

The input to the encoder ...

value BBCard ::=
{
  name "Casey",
  team "Mudville Nine",
  age 32,
  position "left field",
  handedness ambidextrous,
  batting-average { mantissa 250, base 10, exponent -3 }
}

The encoder's trace messages ...

BBCard SEQUENCE: tag = [UNIVERSAL 16] constructed; length = 50
  name IA5String: tag = [UNIVERSAL 22] primitive; length = 5
    "Casey"
  team IA5String: tag = [UNIVERSAL 22] primitive; length = 13
    "Mudville Nine"
  age INTEGER: tag = [UNIVERSAL 2] primitive; length = 1
    32
  position IA5String: tag = [UNIVERSAL 22] primitive; length = 10
    "left field"
  handedness ENUMERATED: tag = [UNIVERSAL 10] primitive; length = 1
    2
  batting-average REAL: tag = [UNIVERSAL 9] primitive; length = 8
    "250*10^-3"
Card encoded.
The encoded data is:
30321605 43617365 79160D4D 75647669 6C6C6520 4E696E65 02012016 0A6C6566
74206669 656C640A 01020908 03323530 2E452D33

The decoder's trace messages ...

BBCard SEQUENCE: tag = [UNIVERSAL 16] constructed; length = 50
  name IA5String: tag = [UNIVERSAL 22] primitive; length = 5
    "Casey"
  team IA5String: tag = [UNIVERSAL 22] primitive; length = 13
    "Mudville Nine"
  age INTEGER: tag = [UNIVERSAL 2] primitive; length = 1
    32
  position IA5String: tag = [UNIVERSAL 22] primitive; length = 10
    "left field"
  handedness ENUMERATED: tag = [UNIVERSAL 10] primitive; length = 1
    2
  batting-average REAL: tag = [UNIVERSAL 9] primitive; length = 8
    "250.E-3"
Card decoded.
Casey of the Mudville Nine has a batting average of 250.E-3
Output from the decoder ...

value BBCard ::=
{
  name "Casey",
  team "Mudville Nine",
  age 32,
  position "left field",
  handedness ambidextrous,
  batting-average { mantissa 250, base 10, exponent -3 }
}

Changed card is the input to the encoder ...
value BBCard ::=
{
  name "Casey",
  team "Mudville Ten",
  age 33,
  position "left field",
  handedness ambidextrous,
  batting-average { mantissa 026, base 10, exponent -2 }
}

The encoder's trace messages ...

BBCard SEQUENCE: tag = [UNIVERSAL 16] constructed; length = 46
  name IA5String: tag = [UNIVERSAL 22] primitive; length = 5
    "Casey"
  team IA5String: tag = [UNIVERSAL 22] primitive; length = 12
    "Mudville Ten"
  age INTEGER: tag = [UNIVERSAL 2] primitive; length = 1
    33
  position IA5String: tag = [UNIVERSAL 22] primitive; length = 10
    "left field"
  handedness ENUMERATED: tag = [UNIVERSAL 10] primitive; length = 1
    2
  batting-average REAL: tag = [UNIVERSAL 9] primitive; length = 5
    "026*10^-2"
Card encoded.
The encoded data is:
302E1605 43617365 79160C4D 75647669 6C6C6520 54656E02 0121160A 6C656674
20666965 6C640A01 02090502 302E3236

The decoder's trace messages ...

BBCard SEQUENCE: tag = [UNIVERSAL 16] constructed; length = 46
  name IA5String: tag = [UNIVERSAL 22] primitive; length = 5
    "Casey"
  team IA5String: tag = [UNIVERSAL 22] primitive; length = 12
    "Mudville Ten"
  age INTEGER: tag = [UNIVERSAL 2] primitive; length = 1
    33
  position IA5String: tag = [UNIVERSAL 22] primitive; length = 10
    "left field"
  handedness ENUMERATED: tag = [UNIVERSAL 10] primitive; length = 1
    2
  batting-average REAL: tag = [UNIVERSAL 9] primitive; length = 5
    "0.26"
Card decoded.
Casey of the Mudville Ten has a batting average of 0.26
Output from the decoder ...

value BBCard ::=
{
  name "Casey",
  team "Mudville Ten",
  age 33,
  position "left field",
  handedness ambidextrous,
  batting-average { mantissa 026, base 10, exponent -2 }
}

Go back to top



 

Copyright © 2009 OSS Nokalva, Inc.   All Rights Reserved.