Contents
This section describes the basic set of functions used to encode and decode ASN.1 messages. You will learn how to initialize or terminate an encoder or decoder, how to use set or get flags that control the behavior of the encoder or decoder, and how to debug and trace errors.
These functions initialize an instance of the OssGlobal variable and the compiler-generated control table or code file used with your application.
ossUinit() and ossWinit() enable you to load a control table or code file compiled as a DLL or as a shared library.
NOTE: Before using other OSS API functions, you must call one of these functions. OssGlobal can be used only once.
If successful, it returns zero. Otherwise, it returns a non-zero value.
For each control table or code file that your application uses, you must allocate and initialize a separate instance of OssGlobal.
If your application uses multiple simultaneous threads, you must keep separate instances of OssGlobal per each thread. To duplicate an instance of OssGlobal for each thread, use ossDupWorld(). Compared to ossinit(), ossDupWorld() has a lower overhead.
ossterm() | ossUterm() | ossWterm()
These functions are used in conjunction with ossinit(), ossUinit(), and ossWinit() after initialization is complete.
In general, when calling these functions, consider the following rules:
You must also call ossWterm() instead of ossterm() when you use OSS DLLs in your application; ossWterm() frees the OSS DLLs.
No value is returned.
In case you have multiple instances of the OssGlobal variable, you must free each instance separately.
ossinit() | ossUinit() | ossWinit()
Decodes a message contained in a buffer of type OssBuf using one of the available encoding rules. The ossDecode() function fills a specified compiler-generated structure (PDU) with values by decoding the input encoding of a similar structure (PDU).
You can preallocate a buffer for the decoded data, and pass the address of the pointer that references your preallocated buffer. In this case, the decoder writes the decoded PDU to your provided buffer. However, after preallocating an output buffer, before calling the decoder each time, you must call the ossSetDecodingLength() function to set the length of the allocated buffer.
After a successful return, the decoded data is accessible through the pointer output. If you preallocated a buffer for the decoded data, the resulting PDU structure can be located anywhere, in any number of pieces, within the buffer. The ossDecode() function is not required to start the structure at the beginning of the buffer and finish it in a single piece. Typically, the opposite is true, with pointers providing the location of each subsequent piece. However, the structure is created just as the .h file defines it.
To retrieve the number of bytes occupied by the decoded data, call ossGetDecodingLength(). If a decoding error occurs and the decoding buffer is preallocated, the contents are unpredictable and should not be used. If you set output to NULL, the decoder frees any temporary memory allocated before exit.
Although it's not recommended for everyone, you might consider partial decoding if you are interested in the contents of only a few fields. Rather than call ossDecode(), which would have decoded the entire PDU, you could instead call ossPartialDecode() to decode only those fields you flag with the OSS.DataCallback directive. For details, see the Partial Decoding section.
If successful, it returns zero. Otherwise, it returns a non-zero value.
OssGlobal w, *world = &w; OssBuf encodedData; /* length and address of encoded data */ DataPacket *DecodedDataPtr = NULL; /* address of decoded data */ int pdu_num; . . . pdu_num = DataPacket_PDU; if (ossDecode(world, &pdu_num, &encodedData, (void **)&DecodedDataPtr)) { ossPrint(world, "%s\n", ossGetErrMsg(world)); /* print error message*/ ossterm(world); retcode = 1; } else { /* Print out the data that was just decoded. */ ossPrint(world, "\nData decoded to:\n\n"); /* successfully decoded */ ossPrintPDU(world, pdu_num, DecodedDataPtr); ossFreePDU(world, pdu_num, DecodedDataPtr); /* free up PDU */ retcode = 0; }
To make sure the decoder fills in the correct compiler-generated structure, we recommend that you always pass the PDU number of the data type used for decoding.
In general, when you decode BER, DER, XER, E-XER, or OER messages, the decoder knows which compiler-generated structure to fill in. In this case, you can set the PDU number variable to a value of zero before calling the decoder:
int myPduNum; . . . . myPduNum = 0; ossDecode(world, &myPduNum, &encodedData, &decodedDataPtr);
Before decoding, the decoder sets the passed PDU number variable equal to the #defined PDU identification constant of the structure filled.
When you decode a message that contains an open type, the decoder will not automatically find its PDU number.
The decoder does not modify the input OssBuf structure. This may cause difficulties in case you decode multiple concatenated PDUs from the same input buffer. To instruct the decoder to set the length field of OssBuf to the number of bytes remaining to be decoded (in the input buffer) and the value field of OssBuf to the beginning of the next encoded PDU, compile your data schema with the -compat decoderUpdatesInputAddress compiler option.
There are three types of encoders: space-optimized, time-optimized, and lean, which share the same interface described above. Each type is contained in its own library file. Therefore, you must explicitly link with the library that contains the type of encoder used. Also, compile your ASN.1 data with the appropriate option (-soed, -toed or -soed -lean).
Encodes input data structures into a stream of bits using one of the available encoding rules.
If successful, it returns zero. Otherwise, it returns a non-zero value.
OssGlobal w, *world = &w; OssBuf encodedData; /* length and address of encoded data */ DataPacket myPacket; /* compiler generated structure */ . . . encodedData.value = NULL; /* Initialize encoder output buffer */ encodedData.length = 0; /* Encode the data. Return non-zero for failure. */ if (ossEncode(world, DataPacket_PDU, &myPacket, &encodedData)) { ossPrint(world, "%s\n", ossGetErrMsg(world)); /* print error msg */ ossterm(world); /* Free up allocated resources */ return 1; }
By default, the Basic Encoding Rules (BER) are used. To switch to different encoding rules, use ossSetEncodingRules(). To make certain encoding rules available at runtime, compile your ASN.1 specification using specific compiler options (-per for PER encodings, for example).
There are three types of encoders: space-optimized, time-optimized, and lean, which share the same interface described above. Each type is contained in its own library file. Therefore, you must explicitly link with the library that contains the type of encoder used. Also, compile your ASN.1 data with the appropriate option (-soed, -toed or -soed -lean).
Frees up buffers allocated by ossEncode() and OBJECT IDENTIFIER value conversion functions (ossEncodedOidToDotVal()). The value field of the OssBuf variable points to the allocated memory.
NOTE: If you have preallocated your own memory buffer before calling the encoder, do not use the ossFreeBuf(). Instead, use your own memory freeing routines.
No value is returned for this function.
OssGlobal w, *world = &w; OssBuf yourEncodedData; /* length and address of encoded data */ . . . retcode = ossEncode(world, DataPacket_PDU, &myPacket, &yourEncodedData; . . . ossFreeBuf(world, yourEncodedData.value);
Frees up memory allocated by the ossDecode() and ossCpyValue() functions.
If you have preallocated the output buffer to the decoder, do not use ossFreePDU().
If successful, it returns zero. Otherwise, it returns a non-zero value.
OssGlobal w, *world = &w; OssBuf encodedData; /* length and address of encoded data */ DataPacket *DecodedDataPtr = NULL; /* address of decoded data */ int pdu_num; . . . pdu_num = DataPacket_PDU; if (ossDecode(world, &pdu_num, &encodedData, (void **)&DecodedDataPtr)) . . . else { /* Print out the data that was just decoded. */ ossPrint(world, "\nData decoded to:\n\n"); /* successfully decoded */ ossPrintPDU(world, pdu_num, DecodedDataPtr); ossFreePDU(world, pdu_num, DecodedDataPtr); /* free up PDU */ retcode = 0; }
Opens or closes a plain text file to redirect encoder/decoder trace output from the screen to the file for functions like: ossPrint(), ossPrintPDU(), ossPrintHex(), etc.
If the specified file already exists, it is overwritten. After closing the file, the trace output returns to the screen or trace window.
If successful, it returns zero. Otherwise, it returns a non-zero value.
OssGlobal w, *world = &w; OssBuf encodedData; int myPduid = MyASN1DataType_PDU; MyASN1DataType myData; ossinit(world, asn1data); /* Turn on trace capabilities */ ossSetFlags(world, ossGetFlags(world) | DEBUGPDU); ossOpenTraceFile(world, "trace.out"); . . . /* Trace to file */ ossPrint(world, "Starting encoder... \n"); ossEncode(world, myPduid, &myData, &encodedData); ossPrint(world, "Finished encoding PDU id %d. \n", myPduid); . . . ossCloseTraceFile(world); ossterm(world);
To capture encoder/decoder trace information, before calling the encoder/decoder, set the DEBUGPDU flag via ossSetFlags().
In a multi-threaded environment, you must call ossOpenTraceFile() for each thread. The first function argument must be a pointer to a separate unshared instance of the OssGlobal structure allocated or initialized for the thread. Also, each thread must write to a different file. If the same output file is used for multiple threads, the result is unpredictable and might cause errors.
If ossLoadMemoryManager() is called while writing trace data to a file, ossOpenTraceFile() must be called again to continue writing the output to a trace file.
Returns a description string for a numeric code returned by functions in this API. Unlike the ossGetErrMsg() function that works with the ossEncode() and ossDecode() functions, the ossDescribeReturnCode() function can be used in conjunction with any OSS API function.
A pointer to a null-terminated string containing description of the given return code. If the return code is invalid or unknown, NULL is returned.
. . . if ((retcode = ossinit(world, ctltbl))) { /* world failed to be initialized, will use NULL */ #ifndef DLL_LINKAGE msg = ossDescribeReturnCode(NULL, retcode); #endif /* DLL_LINKAGE */ ossPrint(NULL, "ossinit() returned %d:%s", retcode, msg ? msg : "<unknown>"); return retcode; } . . .
To receive precise error descriptions, pass a non-NULL preinitialized value of world to the function. A NULL world can be passed only for codes returned by ossinit(), because world is not initialized by that function in case of errors.
When using the OSS DLL runtime on Windows, you must pass a non-NULL preinitialized world to the function. Otherwise, the function will return a NULL value.
The ossGetAVNFlags() function returns the AVN-specific flags set by the ossSetAVNFlags() function.
The ossSetAVNFlags() function controls the behavior of the TOED AVN encoder/decoder.
Here is a detailed description of the flags:
Flag | Description |
---|---|
AVN_DECODE_CONTAINED_IN_HEX |
Instructs the AVN decoder to automatically decode the containing type from a value of a BIT STRING or OCTET STRING type constrained by contents constraints when the value is provided in the hexadecimal form. When the flag is not specified, the decoder leaves the container OCTET STRING or BIT STRING value in the "encoded" field of the C-representation. The flag has no effect unless the code generated by the ASN.1 compiler is C-compiled using the -DOSS_AVN_DECODE_CONTAINED_IN_HEX option. |
AVN_PRESERVE_INCOMPLETE_VALUE_NOTATION |
Instructs the AVN encoder not to free the automatically allocated output buffer and to leave in it the incomplete value notation encoding when the ossEncode() function failed with an error. This can be useful for determining the location of an error. Note that it is the user responsibility to free the buffer by ossFreeMemory() API function. By default, the dynamically allocated buffer is automatically freed after an error. |
In the following example, the ossGetAVNFlags() function is used:
OssGlobal w, *world = &w; unsigned long flags; . . . . flags = ossGetAVNFlags(world); if (flags & AVN_DECODE_CONTAINED_IN_HEX) ossPrint(world, " Auto decoding containing type from HEX is set\n");
In the following example, the ossSetAVNFlags() function is used:
OssGlobal w, *world = &w; void *decoded = NULL, *decoded_hex = NULL;; unsigned char avn_enc[] = "value CO ::= '0201 80'H"; OssBuf input; int rc, rc_hex, pdu = CO_PDU; ... ossSetFlags(world, NOCONSTRAIN | AUTOMATIC_ENCDEC); ossSetEncodingRules(world, OSS_ASN1_VALUE_NOTATION); /* Set input encoding */ input.value = avn_enc; input.length = sizeof(avn_enc) - 1; rc = ossDecode(world, &pdu, &input, &decoded); ossSetAVNFlags(world, ossGetAVNFlags(world) | AVN_DECODE_CONTAINED_IN_HEX); rc_hex = ossDecode(world, &pdu, &input, &decoded_hex); if (!rc) { ossPrint(world, "Decoded value without AVN_DECODE_CONTAINED_IN_HEX\n"); ossPrintPDU(world, CO_PDU, decoded); } if (!rc_hex) { ossPrint(world, "Decoded value with AVN_DECODE_CONTAINED_IN_HEX\n"); ossPrintPDU(world, CO_PDU, decoded_hex); } ...
For the following syntax:
Test DEFINITIONS AUTOMATIC TAGS ::= BEGIN per OBJECT IDENTIFIER ::= {joint-iso-itu-t asn1(1) packed-encoding(3) basic(0) aligned(0)} I ::= INTEGER CO ::= OCTET STRING (CONTAINING I ENCODED BY per) END
The output of the sample:
The decoded value without AVN_DECODE_CONTAINED_IN_HEX:
value CO ::= '020180'H
The decoded value with AVN_DECODE_CONTAINED_IN_HEX:
value CO ::= CONTAINING 384
In the following example, the ossGetAVNFlags() function is used:
OssGlobal w, *world = &w; unsigned long flags; . . . . If (ossGetEncodingRules(world) == OSS_ASN1_VALUE_NOTATION) { flags = ossGetAVNFlags(world); if (flags & AVN_DECODE_CONTAINED_IN_HEX) ossPrint(world, " Auto decoding containing type from HEX is set\n"); }
In the following example, the ossSetAVNFlags() function is used:
OssGlobal w, *world = &w; ... If (ossGetEncodingRules(world) == OSS_ASN1_VALUE_NOTATION) { ossSetAVNFlags(world, ossGetAVNFlags(world) | AVN_DECODE_CONTAINED_IN_HEX); rc = ossDecode(world, &pdu, &input, &decoded); ... }
For the following syntax:
Test DEFINITIONS AUTOMATIC TAGS ::= BEGIN per OBJECT IDENTIFIER ::= {joint-iso-itu-t asn1(1) packed-encoding(3) basic(0) aligned(0)} I ::= INTEGER CO ::= OCTET STRING (CONTAINING I ENCODED BY per) END
The input encoded value:
value CO ::= '0201 80'H
The decoded value without AVN_DECODE_CONTAINED_IN_HEX:
value CO ::= '020180'H
The decoded value with AVN_DECODE_CONTAINED_IN_HEX:
value CO ::= CONTAINING 384
Gets or sets the debugging flags.
The following table contains the available flags and provides a description of their function:
Flag | Description |
---|---|
PRINT_DECODER_INPUT |
Prints the input of the decoder upon entry. Binary encodings (BER, PER, or OER) are converted by calling ossPrintHex(); otherwise ossPrintXML() is called to print the input as formatted XML. This flag is not available for input from a file or socket. |
PRINT_DECODER_OUTPUT |
Prints the output of the decoder right before it exits. |
PRINT_DECODING_DETAILS |
Prints verbose trace messages during decoding. This flag is not available for TOED and LED libraries. |
PRINT_ENCODER_INPUT |
Prints the input of the encoder upon entry. |
PRINT_ENCODER_OUTPUT |
Prints the output of the encoder right before it exits. For binary encodings (BER, PER, or OER), ossPrintHex() is called; otherwise ossPrintXML() is called to print the input as formatted XML. This flag is not available for output written to a file or socket. |
PRINT_ENCODING_DETAILS |
Prints verbose trace messages during encoding. This flag is not available for TOED and LED libraries. |
PRINT_ERROR_MESSAGES |
Prints error messages using appropriate functions (ossEncode(), ossDecode(), for example) when errors occur. |
PRINT_HEX_WITH_ASCII |
Instructs ossPrintHex() to print
ASCII representations formatted as follows:# 000000: 4200 7368 6972 7423 DC74 726F 7573 6572 B.shirt#.trouser # 000010: 73A5 1073 686F 6573 C648 7469 6502 9073 s..shoes.Htie..s |
OSS_DEBUG_LEVEL_0 |
The encoder/decoder will not print diagnostics. This is the default level. |
OSS_DEBUG_LEVEL_1 |
Prints error messages using appropriate functions (ossEncode(), ossDecode()) when errors occur. |
OSS_DEBUG_LEVEL_2 |
Similar to OSS_DEBUG_LEVEL_1. Additionally, prints the input to ossEncode() upon entry, and the output from ossDecode() before exit. |
OSS_DEBUG_LEVEL_3 |
Similar to OSS_DEBUG_LEVEL_2. Additionally, prints the output from ossEncode() before exit, and the input to ossDecode() upon entry. |
OSS_DEBUG_LEVEL_4 |
Similar to OSS_DEBUG_LEVEL_3. Additionally, instructs the encoder and decoder to print verbose trace messages. This flag is not available for TOED and LED libraries. For binary encodings (BER, PER, or OER), ASCII representations of the encoder output and the decoder input are generated. |
If successful, ossGetDebugFlags() returns all debugging flags set. Otherwise, if world is NUL, it returns -1 (unsigned long). If no prior call has been made to ossSetDebugFlags(), a value of zero is returned.
If the call succeeded, ossSetDebugFlags() returns a value of zero. Otherwise, a non-zero value is returned.
OssGlobal w, *world = &w; unsigned long flags; ossSetDebugFlags(world, PRINT_DECODER_INPUT | PRINT_HEX_WITH_ASCII); ... flags = ossGetDebugFlags(world); if (flags & PRINT_HEX_WITH_ASCII) ossPrint(world, "Detailed HEX/ASCII dump:\n"); else ossPrint(world, "Plain HEX dump:\n");
To include debugging capabilities in TOED, define -DOSSPRINT and -DOSSDEBUG=x (x is 1 or greater) while compiling the generated TOED code.
Sets or gets the behavior of the encoder or decoder library using the flags described in the table below.
When using these flags, consider the following rules:
For flags shared by both the encoder and decoder (E/D), you can call ossSetFlags() or ossSetEncodingFlags() and ossSetDecodingFlags() functions one after the other.
ossGetFlags() returns the logical OR of all the flags set by ossSetFlags(), ossSetEncodingFlags(), or ossSetDecodingFlags().
The following table contains the available flags and provides a description of their function (E/D/O indicates that the flag applies to the Encoder, Decoder, or Other):
Flag | Description |
---|---|
AUTOMATIC_ENCDEC (E/D) |
Specifies the automatic encoding and decoding of open types and their containing structures. By default, the encoder or decoder does not handle open types automatically. |
BACK_ALIGN (E) |
Instructs the encoder to right-justify data within your preallocated output buffer. In most cases, the encoder also modifies the argument output->value. To be able to later free the output buffer, save a copy of it before you call ossEncode(). |
COMPACT_XER_ENCODING (E) |
Available for XER encodings. Removes white space and new line symbols from the resulting XER encoding. |
DEBUG_ERRORS (D) |
Prints a diagnostic message upon encountering an error, before attempting to continue decoding. The printed diagnostic message is the first one returned by ossDecode(), regardless of the number of errors. |
DEBUGPDU (E/D) |
Traces data while each PDU is encoded/decoded. Prints a diagnostic message upon encountering an error, before attempting to continue decoding (DEBUG_ERRORS is implied). The printed diagnostic message is the first one returned by ossDecode(), regardless of the number of errors. |
DEFAULT_ALIGN (E) |
Instructs the encoder to use the most efficient alignment in your preallocated output buffer. The data is left-justified if the Packed Encoding Rules, XML Encoding Rules, or Octet Encoding Rules are in use, or if the BER indefinite length form is in use. Otherwise, data is right-justified. In most cases, the encoder also modifies the argument output->value. To be able to later free the output buffer, save a copy of it before you call ossEncode(). |
DEFINITE (E) |
Available for BER and DER. Instructs the encoder to use the definite length form when encoding. |
DETERMINE_ENC_LENGTH (E) |
Instructs the encoder (and related functions) to
generate the total length of an encoding. Recommended when a custom memory manager is used with the ossEncode() function.
NOTE: This flag is deprecated. Use the ossDetermineEncodingLength() API function instead. |
DONT_DO_DECODED / DONT_DO_ENCODED (O) |
ossCmpValue() and ossCpyValue() will not compare or copy the decoded / encoded fields of sent open type structures. Recommended when working with open types. |
DONT_FREE_ENCODED (D) |
The decoder will not free memory allocated for the encoded field of an open type when automatically decoding open types. Memory is usually allocated for the enclosed open type encoding in the outermost call to the decoder. |
DONT_OPTIMIZE_XMLNS (E/D) |
During decoding: instructs the E-XER decoder to optimize an xmlns declaration generation for decoded values of types with the ANY-ELEMENT instruction, and for open types. By default, when the flag is disabled, the decoder tries to determine the minimum necessary set of namespace prefixes to include their namespace declarations in the outermost part of the decoded abstract value; otherwise, the decoder includes all namespace declarations that are in scope for the element being decoded. Available for LED and TOED. During encoding: instructs the encoder to produce declarations for all the namespaces referenced in the input ASN.1 schema into the outermost tag of the generated Extended XER encoding. When this flag is disabled, the encoder declares only namespaces referenced by the PDU to be encoded. Thus you will have a cleaner and less verbose XML, but may slow down the encoder by 5-7% (in certain cases) because it requires an extra recursive pass through the value to be encoded. |
EXER_ENCODING_OF_DEFAULT_VALUES_AS_COMMENTS (E) |
Instructs the E-XER encoder to encode absent DEFAULT fields as XML comments that contain the corresponding default values. |
FRONT_ALIGN (E) |
Instructs the encoder to left-justify data within the preallocated output buffer. |
IGNORE_DEFER_DECODING (E/D) |
Instructs the encoder/decoder to encode/decode open types generated when applying the ASN1.DeferDecoding directive with its containing type. The generated open types can be automatically encoded/decoded if this flag is set, when AUTOMATIC_ENCDEC is also specified. To enable support for this runtime flag in TOED, you must compile TOED generated code file with the IGNORE_DEFER_DECODING_SUPPORTED macro. |
IGNORE_PDU_TAG (D) |
The decoder will not issue a PDU tag mismatch error message when performing the second decoding on an open type marked for deferred decoding. |
INDEFINITE (E) |
Available for the space-optimized BER encoder. Instructs the encoder to use the indefinite length form when encoding. |
NOCONSTRAIN (E/D) |
The encoder/decoder will not perform strict constraint checking, thus improving CPU performance. Not recommended during development for verifying whether your data satisfies all ASN.1 subtype constraints, and if all enumeration values presented for encoding are valid. If the -noConstraints compiler option is specified during ASN.1-compiling of your schema, this flag is ignored. |
NOTRAPPING (E/D) |
Similar to OSS_TRAPPING, it disables signal trapping. Starting with the 8.2.0 version, it is the default flag. For earlier versions, the default behavior of the encoder/decoder is to trap signals. This helps at identifying errors such as passing bad pointers to encoder/decoder API, and to allow the library to return an error instead of crashing. The downside of signal trapping is that it might affect performance, and it is not always thread-safe. We recommend that you disable trapping for multi-threaded applications built with versions older than 8.2.0. |
NO_XML_DECLARATION (E) |
Specified for XER encodings. The encoder will not generate XML header declarations (<?xml version="1.0" encoding="UTF-8"?>) at the beginning of subsequently produced XER encodings (default behavior). |
OLD_STRICT_ENCODING_DECODING_RULES (D) |
Starting with version 10.6, the STRICT_ENCODING_DECODING_RULES flag enforces stricter checking of conformance to encoding rules. For compatibility with pre-10.6 runtimes, use the OLD_STRICT_ENCODING_DECODING_RULES flag, which enforces the same level of conformance checking that was provided by the STRICT_ENCODING_DECODING_RULES flag in previous versions. Both flags override the OSS_RELAXED (RELAXBER, RELAXPER) flag.
To correctly set the OLD_STRICT_ENCODING_DECODING_RULES flag, use the following statement:
ossSet...Flags(world, (ossGet...Flags(world) & ~STRICT_ENCODING_DECODING_RULES) | OLD_STRICT_ENCODING_DECODING_RULES); |
OSS_AUTO_ENCODE_WITHOUT_CHECKING _CONSTRAINT (E) |
Disables constraint checking for values of types constrained by a component relation constraint. The value must not be present in the referred ObjectSet even when ObjectSet is extensible. |
OSS_SKIP_UNKNOWN_CONTENT (D) |
Instructs the E-XER decoder to silently discard any unknown elements and attributes in the input (decoded) XML message. This flag takes precedence over the -relaySafe compiler option, meaning that unknown extensions are not saved if the flag is set. |
OSS_RELAXED (RELAXBER, RELAXPER) (D/O) |
The decoder will not report an error if the input encoding slightly deviates from the ITU-T standards (the Canonical-PER decoder ignores the flag). The admissible deviations are listed below, grouped by encoding rules: For BER encodings:
ERROR-CLASS ::= CLASS { &code OBJECT IDENTIFIER --<ENCODED|OBJECTID 100>-- UNIQUE, &category PrintableString (SIZE(1)) UNIQUE, &Type } WITH SYNTAX {&code &category &Type} |
OSS_TRAPPING (E/D) |
Enables signal trapping. Starting with 8.2.0 version, it is disabled by default. Signal trapping helps at identifying errors such as passing bad pointers to encoder/decoder API, and allows the library to return an error instead of crashing. The downside is that it might affect performance, and it is not always thread-safe. We recommend that you disable trapping for multi-threaded applications built with versions older than 8.2.0. The NOTRAPPING flag is supported for compatibility, but OSS_TRAPPING takes precedence. |
RELAY_OPEN_TYPE_IN_HEX (E) |
Used with XER encoders. Values of open types that cannot be represented as valid XML can be encoded as their hexadecimal equivalent. This ensures that the binary encoding (BER, PER, etc.) can be re-encoded into XER and relayed if it contains undecoded BER or PER open type values. If this flag is not set, the encoder does not validate the contents of pre-encoded open types and places them in binary (assuming it is XML). If this flag is set, the encoder checks that the contents are well formed and places "well-formed" contents into binary (XML). Contents that are not well-formed are placed in HEX. Note that this flag may affect performance. The HEX contents cannot be used:
|
STRICT_CONSTRAINT_CHECKING (E/O) |
Enables the following:
|
STRICT_ENCODING_DECODING_RULES (E/D) |
Enables strict checking of conformance to encoding rules. The flag overrides the OSS_RELAXED (RELAXBER, RELAXPER) flag. When the flag is set, the following are not allowed by the decoder:
|
STRICT_PER_ENCODING_OF_DEFAULT_VALUES (E) |
The PER encoder will not encode components defined with a DEFAULT value when the value to be encoded matches the DEFAULT. To enable support for this runtime flag in TOED, compile the TOED generated code file with the OSS_STRICT_PER_ENCODING_OF_DEFAULT_VALUES macro. |
USE_COMPRESSION (E/D) |
Instructs the decoder to decompress or decrypt the encoded data using the preset decompression or decryption routine before returning the decoded data. The user must ensure that the same algorithm is used by the decoder for decompression or decryption as it was used by the encoder for compression or encryption. When no valid compression or encryption function is set, the encoder will return the BAD_ARG error code. |
For ossSet...Flags(): If successful, it returns zero. Otherwise, it returns a non-zero value.
For ossGet...Flags(): If successful, it returns all the effective flags in place. If world is found NULL, it returns -1. If no prior call has been made to either ossSetFlags(), ossSetEncodingFlags(), or ossSetDecodingFlags(), it returns zero.
OssGlobal w, *world = &w; OssBuf encodedData; int myPduid = MyASN1DataType_PDU; MMyASN1DataType myData, *DecodedDataPtr; . . . ossSetFlags(world, ossGetFlags(world) | BACK_ALIGN); ossEncode(world, myPduid, &myData, &encodedData); . . . ossSetDecodingFlags(world, ossGetDecodingFlags(world) | OSS_RELAXED | DEBUGPDU | OSS_TRAPPING); ossDecode(world, &myPduid, &encodedData, (void **)&DecodedDataPtr);
Each time you call a "set" function, all previous flags are overwritten. To keep the previous settings, first call "get", then perform a logical OR between the returned value and the new flags you want to set. For example:
&ossSetFlags(world, ossGetFlags(world) | OSS_RELAXED);
The ossGetJsonFlags() function returns the JSON-specific flags set by the ossSetJsonFlags() function.
The ossSetJsonFlags() function controls the behavior of the JSON encoder.
Here is a detailed description of the flags:
Flag | Description |
---|---|
JSON_ENC_ABSENT_COMPONENTS |
Instructs the JSON encoder to include the "null" token for absent optional components whose types are not NULL or open types. When the flag is not specified, absent optional components of SET and SEQUENCE types are not encoded. |
JSON_ENC_DEFAULT_VALUES |
Instructs the JSON encoder to encode absent SET or SEQUENCE type components defined with the DEFAULT syntax either as their default value or as "null" depending on the JSON_ENC_ABSENT_COMPONENTS flag settings. When the JSON_ENC_DEFAULT_VALUES flag is not specified, absent components are not encoded. |
JSON_USE_UNICODE_ESCAPE_SEQUENCE |
Instructs the encoder to encode each non-ASCII character in restricted character string type values using the "\uxxxx" unicode escape sequence. When the flag is not specified, non-ASCII characters are UTF-8 encoded. For example, when the flag is not specified, the COPYRIGHT SIGN character is UTF-8 encoded into two octets, 0xC2 and 0xA9. When the flag is set, it is encoded using the "\u00A9" unicode escape sequence. |
JSON_COMPACT_ENCODING |
Instructs the JSON encoder to create a compact JSON encoding with no whitespace and new lines. When the flag is not specified, the encoder inserts whitespace and newlines to improve readability. |
JSON_ENC_CONTAINED_AS_TEXT |
Instructs the JSON encoder to encode values of BIT STRING or OCTET STRING types with contents constraints as text (the JSON value represents the contained value) rather than hex string. |
After a successful return, the specified flags are set to modify the behavior of the encoder starting with its next call.
The ossGetJsonFlags() function returns an unsigned long integer. Upon a successful call, the flags set for the encoder are returned. If world is NULL, a value of (unsigned long) -1 is returned. If no prior call was made to the ossSetJsonFlags() function, a value of zero is returned.
The ossSetJsonFlags() function returns an integer. Upon a successful call, a value of zero is returned; otherwise, a non-zero value is returned.
NOTE: By default, (after the ossInit() call) none of the above JSON flags is set.
In the following example, the ossGetJsonFlags() function is used:
OssGlobal w, *world = &w; unsigned long flags; . . . . flags = ossGetJsonFlags(world); if (flags & JSON_COMPACT_ENCODING) ossPrint(world, "Compact encoding will be created.\n"); else ossPrint(world, "Indented encoding will be created.\n");
In the following example, the ossSetJsonFlags() function is used:
OssGlobal w, *world = &w; OssBuf encodedData; int myPduNum = MyASN1DataType_PDU; MyASN1DataType myData; . . . . if (ossGetEncodingRules(world) == OSS_JSON) ossSetJsonFlags(world, ossGetJsonFlags(world) | JSON_ENC_CONTAINED_AS_TEXT); ossEncode(world, myPduNum, &myData, &encodedData);
For the following syntax:
A ::= SEQUENCE { opaque OCTET STRING (CONTAINING SEQUENCE { name UTF8String, age INTEGER }) } v A ::= { opaque CONTAINING { name "John", age 33 } }
the OCTET STRING value is encoded as hex string:
{ "opaque":"7B0A2020226E616D65223A224A6F686E222C0A202022616765223A33330A7D" }
When the JSON_ENC_CONTAINED_AS_TEXT JSON runtime flag is set, it is encoded in the expanded form:
{ "opaque":{ "containing":{ "name":"John", "age":33 } } }
The ossGetJsonFlags() and ossSetJsonFlags() functions are available since version 10.3.
The ossGetJsonIndentSize() function returns the indentation size used by the JSON encoder. By default, the encoder indents two spaces.
The ossSetJsonIndentSize() function sets the indentation size used by the JSON encoder.
The ossGetJsonIndentSize() function returns an integer value that represents the number of spaces used as an indentation size. If world is NULL, a negative value is returned.
The ossSetJsonIndentSize() function returns an integer. Upon a successful call, a value of zero is returned; otherwise, a non-zero value is returned.
In the following example, the ossGetJsonIndentSize() function is used:
OssGlobal w, *world = &w; int iSize; . . . . iSize = ossGetJsonIndentSize(world); ossPrint(world, "Size of indentation is %d.\n", iSize);
In the following example, the ossSetJsonIndentSize() function is used:
OssGlobal w, *world = &w; OssBuf encodedData; int myPduNum = MyASN1DataType_PDU; MyASN1DataType myData; . . . . if (ossGetEncodingRules(world) == OSS_JSON) ossSetJsonIndentSize(world, 4); ossEncode(world, myPduNum, &myData, &encodedData);
The ossGetJsonIndentSize() and ossSetJsonIndentSize() functions are available since version 10.3.
Gets or sets the encoding rules to be used by the encoder and decoder. PDUs are encoded according to the specified rules. The decoder decodes sent encodings according to the specified rules. By default, the Basic Encoding Rules (BER) is used by the encoder or decoder. To change the default mode, use: -cer, -der, -per, -uper, -cper, -cuper, -xer, -cxer, -exer, -oer, -coer, -json, or -avn compiler options when ASN.1-compiling your schema. To switch between multiple encoding rules at runtime, specify multiple compiler options at ASN.1-compile time.
Starting with version 10.1, the Octet Encoding Rules (OER) and Canonical Octet Encoding Rules as specified by ITU-T Recommendation X.696 | ISO/IEC 8825-7: 2015 are also supported. To use these rules with the ossEncode() and ossDecode() functions, compile with the -oer/-coer option specified and set the OSS_OER/OSS_COER flag using the ossSetEncodingRules() function before calling the encoder/decoder.
For ossSetEncodingRules(): If successful, it returns zero. Otherwise, it returns a non-zero value.
For ossGetEncodingRules(): Returns the currently active rule.
In the following example, the encoder will use the Distinguished Encoding Rules (DER). The control table or code file and header file have been generated with the -ber or -der ASN.1 compiler option.
OssGlobal w, *world = &w; OssBuf encodedData; int myPduid = MyASN1DataType_PDU; MyASN1DataType myData; . . . if(ossGetEncodingRules(world) == OSS_DER) ossPrint(world, "Encoding data using DER"); else ossSetEncodingRules(world, OSS_DER); ossEncode(world, myPduid, &myData, &encodedData);
Retrieves error messages generated by the OSS functions. Call this function when ossEncode(), ossDecode(), ossConvertData(), ossPrintPER(), ossPrintXPER(), ossCompress(), ossUnCompress(), ossXML2Binary(), or ossBinary2XML() returns a non-zero value or when ossDetermineEncodingLength() returns a zero value.
If OssGlobal is NULL, it returns NULL. Otherwise, it returns a pointer to a zero-terminated error message string.
OssGlobal w, *world = &w; OssBuf encodedData; int myPduid = MyASN1DataType_PDU; MyASN1DataType myData; . . . ossPrint(world, "Starting encoder... \n"); if(ossEncode(world, myPduid, &myData, &encodedData)) ossPrint(world, "%s", ossGetErrMsg(world));
Replaces the printf()and fprintf() C functions. The output text is printed to the device that the asn1out field of the OssGlobal structure points to. If world is NULL, the function calls printf().
If successful, it returns the number of written bytes. Otherwise, it returns -1.
OssGlobal w, *world = &w; OssBuf encodedData; int myPduid = MyASN1DataType_PDU; MyASN1DataType myData; . . . ossPrint(world, "Starting encoder... \n"); ossEncode(world, myPduid, &myData, &encodedData); ossPrint(world, "Finished encoding PDU id %d. \n", myPduid);
On certain platforms, ossPrint() calls fprintf(). To port your code to a platform that has a graphical environment (Windows), and to ensure that data trace works correctly, we recommend that you use ossPrint() instead of fprintf().
Prints JSON encodings in a well-formatted manner. We recommend that you use this function when printing JSON encodings.
The ossSetJsonIndentSize() API function can be used to set a custom indentation size. By default, the encoder indents two spaces.
Upon a successful return, the JSON encoding is printed to the stream pointed to by the asn1out field of the OssGlobal structure.
The ossPrintJSON() function does not have a return value.
OssGlobal w, *world = &w; MyASN1PDU *inputData; OssBuf encodedData; . . . . ossEncode(world, myPduNum, inputData, &encodedData); ossPrintJSON(world, encodedData.value, encodedData.length, TRUE);
The ossPrintJSON() function is available since version 10.3.
Displays BER, DER, PER, UPER, CPER, CUPER, OER, COER, and JSON encodings contained in an OssBuf.value. By default, the output of this function is hexadecimal. When the PRINT_HEX_WITH_ASCII debugging flag is set (see ossSetDebugFlags()), the output includes the ASCII representation for printable characters ("." for unprintable characters).
OssGlobal w, *world = &w; OssBuf encodedData; int myPduid = MyASN1DataType_PDU; MyASN1DataType myData; ;. . . ossPrint(world, "Starting encoder... \n"); ossEncode(world, myPduid, &myData, &encodedData); ossPrint(world, "Finished encoding PDU id %d. \n", myPduid); ossPrint(world, "\nData encoded to:\n"); ossPrintHex(world, (char*)encodedData.value, encodedData.length);
A BER encoded IA5String "Hello" yields the following output:
16054865 6C6C6F
With PRINT_HEX_WITH_ASCII enabled:
# 000000: 1605 4865 6C6C 6F ..Hello
The output text is printed to the device pointed to by the asn1out field of the OssGlobal structure.
These functions convert and print the null-terminated input string, formatted as "'xx...xx'H", into a human readable text or a dotted notation IP-address, respectively.
Each xx represents a single character or an IP octet in HEX form. Non-printable characters are printed as "?". These functions are especially useful with the OSS.PrintFunctionName directive.
ossPrintOctetAsASCII() prints the string '4578616D706C65204F7267616E697A6174696F6E'H as follows:
Example Organization
ossPrintOctetAsIPAddress() prints the string '7F000001'H as follows:
127.0.0.1
The output text is printed to the stream pointed to by asn1out field of the OssGlobal structure.
Prints a stream of octet-aligned data bits as a BCD string. The function was added in version 10.2.0.
The ossPrintOctetAsBCDString() function does not have a return value.
The ossPrintOctetAsBCDString() function is especially useful when used with the OSS.PrintFunctionName directive. For more information, see Compiler Directives.
Prints a stream of octet-aligned data bits as a TBCD string. The function was added in version 10.2.0.
The ossPrintOctetAsTBCDString() function does not have a return value.
The ossPrintOctetAsTBCDString() function is especially useful when used with the OSS.PrintFunctionName directive. For more information, see Compiler Directives.
Converts a null-terminated input string formatted as "'xx...xx'H" into a human-readable timestamp format, YYYYMMDDhhmmss[+-]hhmm, and prints it. Each of the nine input hexadecimal xx pairs except for the seventh are treated as two decimal xx digits. The seventh pair should be a hexadecimal code of either a plus (+) or minus (-) ASCII character. Unexpected hex digits are printed as question marks (?). This function is especially useful with the OSS.PrintFunctionName directive. When the input string length is not 21, the string is printed as is.
ossPrintOctetAsTimeStamp() prints the string '1507061432002B0600'H as follows:
20150706143200+0600
ossPrintOctetAsTimeStamp() prints the incorrect string 'F5A70B1C32DE2FABCD'H as follows:
???5?70?1?32???????
The output text is printed to the stream pointed to by the asn1out field of the OssGlobal structure.
Serializes the content of compiler-generated structures (before encoding or after decoding) into the standardized ASN.1 value notation format, then writes the content to the standard output.
If successful, it returns zero. Otherwise, it returns a non-zero value.
MyASN1DataType ::= SEQUENCE { field1 IA5String, field2 INTEGER }
C representation:
#define MyASN1DataType_PDU 1 typedef struct MyASN1DataType { char *field1; int field2; } MyASN1DataType;
Application code excerpt:
OssGlobal w, *world = &w; OssBuf encodedData; int myPduid = MyASN1DataType_PDU; MyASN1DataType myData; . . . myPduid = MyASN1DataType_PDU; myData.field1 = "Hello"; myData.field2 = strlen(myData.field1); ossPrintPDU(world, myPduid, &myData);
ossPrintPDU() output:
value MyASN1DataType ::= { field1 "Hello", field2 5 }
Allows printing of PDU values in compiler-generated structures into a C-string before encoding or after decoding.
There are two typical use cases:
OssGlobal w, *world = &w; OssBuf outputData; int myPduNum = MyASN1DataType_PDU; MyASN1DataType myData; . . . . outputData.length = 0; outputData.value = NULL; . . . . ossPrintPDUToBuffer(world, myPduNum, &myData, &outputData); . . . . ossFreeBuf(world, outputData.value);
Decodes and prints a human readable representation of the input PER encoding (aligned or unaligned).
ossPrintXPER() prints in a web-friendly XML format. The human readable representation of PER encoding includes fields names, padding bits, location in the message, and other encoding details. You can specify your own printing and formatting function (via UserPrintPer argument), therefore all the information about the input PER encoding is passed in a generic data structure, allowing you to print them in your custom format. These functions are useful during debugging and for writing protocol analyzers.
ossPrintPER() and ossPrintXPER() are not available for TOED, and must be linked with the SOED library.
NOTE: This utility is not part of the general OSS API but is available separately in its own library file (contact Sales <info@oss.com> for more information). The PER Encoder Analyzer is only available on common platforms like Windows, Linux, and Solaris, and may not be available for your embedded system port. If you are interested in PrintPER for your platform, contact Sales <info@oss.com>.
Two flags affect the output of ossPrintXPER():
If successful, it returns zero. Otherwise, it returns a non-zero value. The non-zero value has the same meaning as the return value of ossDecode().
For a complex PDU specified as:
Foo ::= SEQUENCE { a INTEGER (250..253) OPTIONAL, ..., [[ b NumericString (SIZE(3)), c INTEGER ]], ..., d BOOLEAN OPTIONAL } fooValue Foo ::= { a 253, b "123", c 20000, d TRUE }
When you invoke ossPrintPER() with the OSS_HEXBYTES | OSS_PRINT_ABSREF | OSS_PRINT_OFFSET | OSS_PRINT_TYPE_INFO | OSS_PRINT_COMMENTS flags, the following output is generated:
PER unaligned Encoding:
FC04148D 00938800 value Foo ::= { --TYPE INFORMATION: SEQUENCE --OFFSET: 0,0 --extension flag: <.1> --preamble: <11> --bit #0 = 1: 'a' is present --bit #1 = 1: 'd' is present a 253, --TYPE INFORMATION: INTEGER (250..253) OPTIONAL --FULL NAME: a --OFFSET: 0,3; LENGTH: 0,2 --contents: <11> d TRUE, --TYPE INFORMATION: BOOLEAN OPTIONAL --FULL NAME: d --OFFSET: 0,5; LENGTH: 0,1 --contents: <1> --extension preamble size flag: <0> (preamble size <= 64) --extension preamble length: <0.00000> (decoded as 1) --extension preamble: <1> --bit #0 = 1: version brackets that contain: --'b' --'c' --is present --[[ --extension length: <00.000101> (decoded as 5) b "123", --TYPE INFORMATION: NumericString (SIZE(3)) --FULL NAME: b --OFFSET: 2,6; LENGTH: 1,4 --contents: <00>.8D.<00> c 20000 --TYPE INFORMATION: INTEGER --FULL NAME: c --OFFSET: 4,2; LENGTH: 3,0 --length: <000000.10> (decoded as 2) --contents: <010011>.88.<00> --trailing bits: <0000> --]] } --PDU padding: <00> --TOTAL LENGTH: 8,0
When you specify your own printing or formatting function with userPrintPer, the following structure is passed as a parameter:
struct PrintPerRecord { unsigned char typeId; /* identifies the present record type */ ossBoolean possibleLast; /* used when typeId = OSS_ASN1_TYPE TRUE, if there is a chance that this value is the last element of constructed type */ void *decodedContent; /* decoded contents in "display" format */ char *typeName; /* name of the ASN.1 type */ char *fieldName; /* name of a field */ char *qualifiedName; /* "full" name */ char *qualifiedNameOfTopRecord; /* name of the top level record */ char *qualifiedNumber; /* identifier of the record in a set of records for example, 1.2.1.3 */ char *qualifiedNumberOfTopRecord; /* identifier of top record; e.g 1.2.1 */ unsigned int depth; unsigned char *encodedContent; /* encoding of the record */ unsigned char encodedBitOffset; /* the offset of the encoding */ unsigned long length; /* length of encoding (in bits) */ unsigned int numberOfSimplestRecord; /* number of simplestRecords */ struct PrintPerSimplestRecord *simplestRecords; /* array of logical parts */ unsigned char bitsPerContentUnit; /* usually - 8, but could differ for strings with constraints specified */ unsigned int offset; /* offset from a start of encoded data */ ossBoolean allocMem; /* TRUE if decodedContent points to allocated memory */ struct PrintPerRecordAddition *addition; };
By default, ossPrintPER() sends its output to the stream pointed to by the asn1out field of the OssGlobal structure.
The PER Encoder Analyzer comes with a set of default XML stylesheets (.xsl files) to help you display the generated XML output in a user-friendly ASN.1-tuned format.
To use this function, you need a separate library (in addition to the regular encoder/decoder). When you include this functionality into your application, also include osspasn.h and the library file libprintasn.a (on UNIX systems) or printasnmt.lib (on Windows systems) to build successfully.
Used for testing a sample PDU by invoking a sequence of operations, including: encoding, decoding, printing, copying, comparing, and freeing.
This function is useful for beginners learning how to use the OSS ASN.1/C Tools, and for advanced users who want to see a particular data structure in encoded and decoded format.
If successful, it returns zero. Otherwise, it returns a non-zero value.
By default, ossTest() prints to the stream pointed to by the asn1out field of the OssGlobal structure.
The -test ASN.1 compiler option is an alternative method of testing the encoding/decoding of your data. When this option is specified, a main() function is produced in the ASN.1 compiler-generated C file. The main() function calls ossTest(). Then, you compile and link the ASN.1-compiler-generated C file, and run the executable. Note that you must define the types and the values (value references) that is tested.
The ossTestPD() function only becomes available when you use the TOED library and employ either the -enablePartialDecode or -partialDecodeOnly option at ASN.1 compile time.
The ossTestPD() function returns an integer. Upon a successful call, a value of zero is returned; otherwise, the last error code encountered is returned. For more information about the OSS API function error codes, see the ASN.1/C API Return Codes section.
Upon a successful return, the passed PDU is encoded and partially decoded. During partial decoding, tracing information about the callback functions calls and the values of the fields to which the DataCallback directive is applied are printed to the stream specified by the asn1out field of the OssGlobal structure.
OssGlobal w, *world = &w; OssBuf encodedData; int myPduNum = MyASN1DataType_PDU; MyASN1DataType myData; . . . . ossTestPD(world, myPduNum, &myData);
Checks whether the last PDU decoded by the ossDecode() function contained at least one unknown SEQUENCE, SET, or CHOICE type extension. The presence of unknown extensions indicates that the sender is using a newer ASN.1 specification version.
Note that this feature is disabled by default due to some performance and size overhead. To enable it, C-compile the generated code using the -DOSS_DETECT_UNKNOWN_EXTENSION option. If the feature is not enabled, the ossUnknownExtensionFound() function returns 0 regardless of the presence of unknown extensions.
OssGlobal w, *world = &w; int rc, pdunum; void *data; OssBuf encodedData; . . . if (ossDecode(world, &pdunum, &encodedData, (void **)&data) == PDU_DECODED) { ossPrint(world, "PDU successfully decoded.\n"); rc = ossUnknownExtensionFound(world); if (rc > 1) ossPrint(world, "ossUnknownExtensionFound() failed with return code %d!\n", rc); else ossPrint(world, "Unknown extension %sfound!\n", rc == 1 ? "" : "NOT "); }
Prints:
Resulting string: Unknown extension found!
The functions described in this section enable greater control over the storage and retrieval of data manipulated by the encoder/decoder. For more information, see Memory, File, Sockets, and PDU Handling.
Substitutes or restores the default memory allocation of OssGlobal memory functions (OssGlobal.mallocp, OssGlobal.freep, etc.) with preallocated chunks of memory that can hold complete PDU data during subsequent encoding or decoding operations. You don't need to allocate memory dynamically during encoding or decoding, which means that performance is increased.
A memory handle controls every chunk (clean-up, delete, set active, etc.). You can create multiple chunks by calling ossCreateMemoryHandle() every time. However, only one chunk is active for every call. After the last chunk is deleted, the default memory allocation functions are restored in OssGlobal.
When using or customizing OssGlobal, other memory allocation functions will use the chunk under the active memory handle. Therefore, when using memory handles, make sure you do not specify the ossSetUserMallocFreeRealloc() function.
If successful, ossCreateMemoryHandle() returns a new memory handle. Otherwise, it returns NULL.
If successful, ossDeleteMemoryHandle() returns zero.
OssGlobal w, *world = &w; OssMemoryHandle *encMemory; . . . if (!(encMemory = ossCreateMemoryHandle(world, DEFAULT_CHUNK_LENGTH))) appretcode = EXIT_FAILURE; . . . if ((retcode = ossEncode(world, BBCard_PDU, &myCard, &encodedData)) != 0) appretcode = retcode; . . . if ((retcode = ossDeleteMemoryHandle(world, encMemory)) != 0) appretcode = retcode;
Memory handles decrease the number of calls to the system memory allocation or release functions. You can use one call for one or more decode operations.
Unlike user preallocated buffers, memory handles do not limit the size of encoded or decoded data. Each handle is a list of relatively large memory blocks (you set the minimal size of a block) from which the library allocates the output memory.
The content of memory handles is private and it is not described in OSS header files.
The ossCreateMemoryHandle() function returns NULL if the application is linked with the RTOED library and the generated codefile is C-compiled without the -DOSS_RTOED_MEMORY_HANDLES_SUPPORTED option.
Marks memory that is associated with the given memory handle as unused, without deallocating it on the system level (with world->freep). You can use it to rapidly free up and reuse memory on multiple encode or decode operations. Unlike ossFreePDU() or other similar functions, it does not traverse the decoded PDU tree, and does not call a system memory release function for each block of memory. To deallocate the handle, call the ossDeleteMemoryHandle() function.
If successful, ossCleanMemoryHandle() returns zero. Otherwise, it returns a non-zero value.
OssGlobal w, *world = &w; OssMemoryHandle *encMemory; . . . if (!(encMemory = ossCreateMemoryHandle(world, DEFAULT_CHUNK_LENGTH))) appretcode = EXIT_FAILURE; . . . if ((retcode = ossEncode(world, BBCard_PDU, &myCard, &encodedData)) != 0) appretcode = retcode; . . . if ((retcode = ossCleanMemoryHandle(world, encMemory)) != 0) { appretcode = retcode; . . .
Returns the size of the encoded data that ossEncode() creates. You can find the size of the buffer for storing the output of the encoder without extensive memory allocations. This function is especially useful in applications that need to minimize the amount of allocated memory. When using this function, we recommend that you perform empirical test calls of ossEncode(), and check the OssBuf.length field after each call.
If successful, ossDetermineEncodingLength() returns the number of bytes occupied by the encoding data. Otherwise, it returns a length of zero.
OssGlobal w, *world = &w; OssBuf encodedData; int myPduid = MyASN1DataType_PDU; MyASN1DataType myData; long encodingLength; . . . encodingLength = ossDetermineEncodingLength(world, myPduid, &myData); ossPrint(world, "Encoding Length: %ld.", encodingLength);
Returns the total length (including tags, lengths, and contents) of a BER/DER definite-length encoding passed in a buffer.
If successful, ossDetermineMessageLength() returns the number of bytes occupied by the encoding data. If the buffer does not contain valid BER/DER definite-length encodings, it returns a value of zero.
OssGlobal w, *world = &w; OssBuf encData; int myPduNum = MyASN1DataType_PDU; MyASN1DataType myData; . . . ossEncode(world, myPduNum, &myData, &encData); ossPrint(world, "Encoding length: %ld.", ossDetermineMessageLength(&encData));
ossDetermineMessageLength() does not work with the file memory manager.
Returns the number of extra bits padded to the end of a PER encoding (aligned or unaligned). This function is useful for those applications that must obtain the exact size of the encoding, excluding the trailing pad bits. This function checks the runtime environment to see how many pad bits were added by the encoder for the previous encoding. It is available for PER encodings.
If successful, ossDetermineNumberOfPadBits() returns the number of bits (zero to seven) padded to the last octet of the previous value encoded. If an error occurs, it returns a value that is less than zero or greater than seven.
Returns the size of the buffer that ossPrintPDUToBuffer() would create if it were called to print the sent PDU. You can find the size of the buffer needed to store the output, without allocating memory with ossPrintPDUToBuffer(). This function is used primarily in applications that want to minimize the amount of memory allocated.
The ossDeterminePDUBufferLength() function returns a long INTEGER. If successful, it returns the number of octets to be occupied by the printed PDU value. Otherwise, it returns a length of zero.
OssGlobal w, *world = &w; int myPduNum = MyASN1DataType_PDU; MyASN1DataType myData; long bufferLength; . . . . bufferLength = ossDeterminePDUBufferLength(world, myPduNum, &myData); ossPrint(world, "Buffer Length: %ld.\n", bufferLength);
Allocates or deallocates a block of memory (similar to ossEncode() | ossDecode()). When you call the ossSetUserMallocFreeRealloc() function for custom memory allocation, deallocation, and reallocation, the custom memory allocator is used. If the memory handle is active, memory is taken or returned from or to the handle.
ossGetInitializedMemory() initializes the allocated block to zero.
ossFreeMemory() does not return a value.
If successful, ossGetMemory() and ossGetInitializedMemory() return a pointer to the newly allocated block of memory. Otherwise, they return NULL.
#define BUF_SIZE 1024 OssGlobal w, *world = &w; OssBuf buf; . . . buf.value = (unsigned char *)ossGetMemory(world, BUF_SIZE); buf.length = BUF_SIZE; . . . ossFreeMemory(world, buf.value);
When you call ossCleanMemoryHandle() or ossDeleteMemoryHandle() while using memory handles, the memory block allocated by ossGetMemory() will also become obsolete.
These functions are especially used by helper macros and helper list API functions generated by the OSS ASN.1 compiler with -helperMacros, -helperListAPI command-line options or corresponding directives during ASN.1-compiling. They are hidden from the application that uses corresponding generated macro and function names.
If helper macros functions cannot be used with the application, it is recommended to explicitly call ossGetMemory() or ossFreeMemory() to allocate or deallocate memory, since they support custom memory and memory handles by default, and hide the memory handling details.
Do not use the ossGetMemory() function pointer as the first parameter for the ossSetUserMallocFreeRealloc() function. The pointer enforces ossGetMemory() to call itself, which will result an endless loop when trying to allocate memory.
The ossSetActiveMemoryHandle() function instructs OSS API functions to back up and replace current memory allocation routines in OssGlobal with the given memory handle.
When the handle pointer is NULL, it instructs the library to disable the memory handle allocation mode and use the previously backed up ones (dynamic memory allocation mode, for example).
The ossGetActiveMemoryHandle() function returns a pointer to the memory handle that has been previously set by ossSetActiveMemoryHandle() or (implicitly) by ossCreateMemoryHandle(). A NULL is returned if there is no active memory handle.
If successful, ossGetActiveMemoryHandle() returns the active memory handle. If there is none, it returns NULL.
If successful, ossSetActiveMemoryHandle() returns a value of zero. Otherwise, it returns a non-zero error code.
OssGlobal w, *world = &w; OssMemoryHandle *encMemory, *decMemory; . . . encMemory = ossCreateMemoryHandle(world, DEFAULT_CHUNK_LENGTH); decMemory = ossCreateMemoryHandle(world, DEFAULT_CHUNK_LENGTH); . . . ossPrint(world, "Setting the encoder memory handle as active..."); if (ossSetActiveMemoryHandle(world, encMemory)) != 0) . . . else if (ossGetActiveMemoryHandle(world) == encMemory) ossPrint(world, "Using the encoder memory handle."); else if (ossGetActiveMemoryHandle(world) == decMemory) ossPrint(world, "Using the decoder memory handle."); else if (ossGetActiveMemoryHandle(world) == NULL) ossPrint(world, "Using the dynamic memory allocation mode."); . . .
Used with the file and socket memory manager.
ossSetBuffer() sets an initial buffer before reading encoded data from a TCP/IP socket or an input file. When you use this function, the decoder first reads the encodings in the initial buffer, then the encodings whose references are passed as input.
ossGetBuffer() returns the trailing buffer of undecoded data left from the previous call to the decoder in the TCP/IP socket or the set initial buffer.
When allocating memory for the OssBufExtended.value, use the (*world->mallocp)() function pointer. Upon completion of decoding, the decoder will free the initial buffer memory. Memory returned by ossGetBuffer() (OssBufExtended.value field) belongs to the memory manager and its contents may change upon subsequent calls of the ossDecode() function. Contents of the buffer may be overwritten when decoding from a file after decoding from a socket. To be able to use it after subsequent decoding operations, make a copy of the data returned by ossGetBuffer().
If successful, ossGetBuffer() | ossSetBuffer() returns zero. Otherwise, it returns CANT_SET_START_BUF.
In the following example, the decoder decodes the encodings within initialBuf before decoding the encodings referenced through encodedData:
OssGlobal w, *world = &w; OssBuf encodedData; OssBufExtended initialBuf; int myPduNum = MyASN1DataType_PDU; . . . initialBuf.value = (unsigned char *)ossGetMemory(1024); ; initialBuf.length = 1024; /* size of initial buffer */ initialBuf.byteOffset = 0; /* offset in buffer from where data starts */ /* populate initialBuf.value with the encoded data (say from file or network) */ . . . ossSetBuffer(world, &initialBuf); ossDecode(world, &myPduNum, &encodedData, (void **)&decodedDataPtr);
When you call ossSetBuffer() after decoding from a TCP/IP socket, any undecoded data left from previous calls to the decoder are lost.
Returns the number of bytes that the decoder reads from the input buffer during the previous decoding. This function is especially useful when decoding from a buffer containing multiple concatenated PDUs in either plain memory or a file.
If successful, ossGetBytesReadByDecoder returns the number of bytes read from the input buffer during the previous decoding. If an error occurs, the returned value reflects the position in the input buffer where the error was detected.
OssGlobal w, *world = &w; OssBuf encodedData; int myPduNum = MyASN1DataType_PDU, rc; MyASN1DataType myData, *DecodedDataPtr; long bytesRead; . . . rc= ossDecode(world, &myPduNum, &encodedData, (void **)&DecodedDataPtr); bytesRead = ossGetBytesReadByDecoder(world); if(rc) /* Decoder returned a failure code */ ossPrint(world, "Error at position %ld in the buffer.", bytesRead); else /* Decoding finished successfully */ ossPrint(world, "%ld bytes decoded.", bytesRead);
Returns the total number of bytes occupied by the last decoded PDU. Note that the output buffer of the decoder does not need to consist of contiguously-allocated memory; rather, the decoded data may be stored in a tree structure. To copy the decoded data, use ossCpyValue() or copy each field separately, instead of using memcpy().
If successful, ossGetDecodingLength returns the total number of bytes occupied by the last decoded PDU. Otherwise, it returns a value of -1.
OssGlobal w, *world = &w; OssBuf encodedData; int myPduNum = MyASN1DataType_PDU; MyASN1DataType myData, *DecodedDataPtr; long lengthOfDecodedData; . . . ossDecode(world, &myPduNum, &encodedData, (void **)&DecodedDataPtr); lengthOfDecodedData = ossGetDecodingLength(world);
To determine how much memory you should use for a preallocated output buffer for the decoder, call the ossGetDecodingLength() function repeatedly with different expected types of input data. By doing so, you can allocate more memory than the highest value received.
ossSetDecodingLength() overwrites the last decoding length stored by the decoder. Thus, you must call ossGetDecodingLength() after calling ossDecode() and before ossSetDecodingLength().
Indicates the output buffer length for the next invocation of ossDecode(). Must be called prior to every invocation of ossDecode() whenever the output buffer is preallocated.
If successful, ossSetDecodingLength() returns zero. Otherwise, it returns a non-zero value.
OssGlobal w, *world = &w; OssBuf encodedData; int myPduNum = MyASN1DataType_PDU; void *DecodedDataPtr; . . . DecodedDataPtr= (void*)malloc(1024); /* preallocate output buffer */ . . . ossSetDecodingLength(world, 1024); ossDecode(world, &myPduNum, &encodedData, (void **)&DecodedDataPtr);
The output buffer length applies only if the output buffer pointer is non-NULL.
Fills memory usage statistics structure OssMemoryHandleStat for the memory handle passed on input. The mode argument controls the level of details and printing of the memory layout and fragments within a handle.
The OssMemoryHandleStat structure is defined as:
typedef struct ossMemoryHandleStat { unsigned int nodes; size_t system_allocated; struct { size_t used_internally; size_t user_allocated; size_t user_free; } detail; } OssMemoryHandleStat;
The following modes are currently defined:
#define OSS_MH_BRIEF 0 #define OSS_MH_DETAIL 1 #define OSS_MH_DETAIL_TRACE_HANDLE 2 #define OSS_MH_DETAIL_TRACE_BLOCKS 3 #define OSS_MH_DETAIL_TRACE_FRAGMENTS 4
For the OSS_MH_BRIEF mode, the function returns brief statistics, including the total amount of system memory allocated, system_allocated, and the number of memory chunks in use, nodes.
For the OSS_MH_DETAIL mode, the function returns the amount of actually used memory, user_allocated, the amount of available memory, user_free, and the amount of memory reserved for internal needs, used_internally. The sum of these three numbers is equal to the memory block size.
The remaining flags control the printing information produced by the function. The following code is produced with the OSS_MH_DETAIL_TRACE_FRAGMENTS flag:
Handle: 0x007c2bd0 Block #1 [0x007c6fb8]: 4128 bytes Fragment #1 [0x007c6fd4]: status = 'free', length = 120 Fragment #2 [0x007c705c]: status = 'used', length = 192 Fragment #3 [0x007c712c]: status = 'last/free', length = 3768 Block summary (bytes): 192 allocated, 3888 free, 48 used internally Handle summary (bytes): 192 allocated, 3888 free, 84 used internally
The flag below can be used for any mode value to suppress printing pointers (values in brackets in the example above) which is useful when comparing results of multiple executions of the same test application:
#define OSS_MH_NO_PTR_IN_TRACE 0x20
If successful, ossGetMemoryHandleStat() returns zero. Otherwise, it returns a non-zero value.
Used with the file and socket memory managers. These functions get or set the data size threshold. The decoder will not create a temporary file to store the output of a type marked with the OSS.OBJHANDLE | NOCOPY directive. PDUs larger than the threshold are decoded to a temporary output file, while the ones smaller than the indicated threshold are decoded to regular memory.
By default, the threshold value is set to zero, thus forcing all values for types marked with OSS.OBJHANDLE | OSS.NOCOPY to be copied to temporary files. If the ossblock field of OssGlobal is set, the threshold cannot exceed it.
ossGetMinFileSize() returns the threshold. ossSetMinFileSize() returns the threshold value. If the return value does not match the specified value, it might indicate that problems were encountered (the specified value was greater than the set ossblock variable, for example).
OssGlobal w, *world = &w; long minFileSize; . . . minFileSize = ossSetMinFileSize(world, 1024); if(minFileSize == 1024) ossPrint(world, "Minimum threshold successfully set."); . . . minFileSize = ossGetMinFileSize(world); if(minFileSize >= 1024) ossPrint(world, "1kB chunks are in use.");
Used with the file, socket, and OSAK memory managers to associate the encoder or decoder data with a file, TCP/IP socket, or OSAK buffer as a source or destination of PDU values.
ossMarkObj() marks the value field of either an OssBuf or a length-value-pair structure referencing data in a file or a socket. It returns a handle to be passed to the encoder or decoder. To directly access data marked with the ossMarkObj() function, unmark the associated object with ossUnmarkObj().
If successful, ossMarkObj() returns a non-NULL handle to a file, socket, or OSAK buffer. Otherwise, a NULL handle (indicating memory problems were encountered) or a value of -1 (indicating that objType is not a valid object type) is returned.
If successful, ossGetObj() | ossUnmarkObj() returns the file name or the socket identification number containing the data. Otherwise, it returns OSS_UNKNOWN_OBJECT .
In the following example, the encoder writes its output to the file named encoder.out. This file is given to the decoder to retrieve the original data. The ossMarkObj() function is called before calling the encoder, then before calling the decoder.
OssGlobal w, *world = &w; OssBuf encodedData; char charFilename[64]; int myPduNum = MyASN1DataType_PDU; MyASN1DataType myData; MemMgrHdl = ossLoadMemoryManager(world, OSS_FILE_MEMMGR, NULL); . . . encodedData.value = ossMarkObj(world, OSS_FILE, "encoder.out"); encodedData.length = 0; ossEncode(world, myPduNum, &myData, &encodedData); . . . ossPrint(world, "Encoding file %s", ossGetObj(world, encodedData.value)); . . . encodedData.value = ossMarkObj(world, OSS_FILE, "encoder.out"); encodedData.length = 0; ossDecode(world, &myPduNum, &encodedData, (void **)&DecodedDataPtr); . . . ossFreeBuf(world, encodedData.value); /* free buffer for encoded data */
To delete a temporary output file when calling ossFreePDU(), make sure it remains "marked".
To encode from a file and decode to a temporary file, use the OSS.OBJHANDLE | OSS.NOCOPY directive. To encode to a file and decode from a file, you do not need to use the OSS.OBJHANDLE | OSS.NOCOPY directive.
When you use these functions, specify the file or socket memory manager library file (ossfmgmt.obj or osssmgmt.obj) before the SOED library file (ssoeddefa.lib).
Sets or gets memory allocation, deallocation, and reallocation functions used by the encoder or decoder. By default, allocation, deallocation, and reallocation operations are performed by malloc(), free(), and realloc() C functions, respectively (stored as pointers in world->mallocp, world->freep, and world->reallocp).
OssGlobal myWorld, *w = &myWorld; void *(CDECL_ENTRY_FPTR *oldMallocp)(OssGlobal *world, size_t size); void *(CDECL_ENTRY_FPTR *oldReallocp)(OssGlobal *world, void *buf, size_t size); void (CDECL_ENTRY_FPTR *oldFreep)(OssGlobal *world, void *buf); void * CDECL_ENTRY_FDEF myMalloc(OssGlobal *world, size_t size){...}; void * CDECL_ENTRY_FDEF myRealloc(OssGlobal *world, void *buf, size_t size){...}; void CDECL_ENTRY_FDEF myFree(OssGlobal *world, void *buf){...}; . . . /* Save original and set new allocation functions */ ossGetUserMallocFreeRealloc(w, &oldMallocp, &oldFreep, &oldReallocp); ossSetUserMallocFreeRealloc(w, myMalloc, myFree, myRealloc); . . . /* Restore original allocation functions */ ossSetUserMallocFreeRealloc(w, oldMallocp, oldFreep, oldReallocp); . . .
Available on the Microsoft Windows platform. Enables the user to switch between the available memory managers at run time. The memory managers are used by the encoder/decoder to handle allocation, deallocation, storage, and retrieval of data. For more information about the OSS memory managers, see Memory, File, Sockets, and PDU handling.
If successful, ossLoadMemoryManager() returns the handle of the loaded DLL. Otherwise, it returns a value of zero.
OssGlobal w, *world = &w; HINSTANCE MemMgrHdl; . . . MemMgrHdl = ossLoadMemoryManager(world, OSS_FILE_MEMMGR, NULL); if (!MemMgrHdl) ossPrint(world, "File memory manager not loaded."); . . .
When freeing a PDU, make sure you use the same memory manager that was used to create it.
These functions are used with the file and socket memory managers. The "open" functions enable you to keep the specified file open across multiple decoder or encoder operations. This is useful for applications that decode or encode multiple concatenated PDUs from or to a file. Thus, you can avoid the extra overhead experienced while opening files multiple times. To associate the encoding file with the encoder or decoder, call the ossMarkObj() function.
If successful, the value returned is zero. Otherwise, the value returned is non-zero.
OssGlobal w, *world = &w; OssBuf encodedData; int myPduNum = MyASN1DataType_PDU; MyASN1DataType *DecodedDataPtr = NULL; char charFilename[64]; . . . encodedData.value = (unsigned char *)ossMarkObj(world, OSS_FILE, "encoded.ber"); encodedData.length = 0; ossOpenDecoderInputFile(world, "encoded.ber"); ossDecode(world, &myPduNum, &encodedData, (void **)&decodedDataPtr); . . . ossCloseDecoderInputFile(world);
When you use the same file as encoder output and as decoder input file in the same application, you must call ossCloseEncoderOutputFile() before calling ossOpenDecoderInputFile().
To decode or encode a single PDU from or to a file, you can call the ossMarkObj() function, while passing it the filename each time before calling the decoder/encoder, instead of using "open" or "close" functions.
Used with the socket memory manager to set a timeout for TCP/IP sockets read or write operations during decoding or encoding from or to a TCP/IP socket. Allows recv() and send() socket functions to complete without blocking.
Enables you to skip pad bytes in the input encoding. The OssBuf.value is advanced until it points to the next byte that does not match pad_byte. OssBuf.length is reduced by the number of skipped bytes. For SOED, ossSkipPadBytes() can be used with the file or socket memory manager, in which case it may fail with a OSS_TIMEOUT_EXPIREDor other non-fatal socket errors. The function can be called multiple times to obtain a successful outcome.
If successful, ossSkipPadBytes() returns a value of zero. Otherwise, it returns a non-zero value. When all pad bytes are skipped and the non-pad byte is not reached, it returns the MORE_INPUT error.
When using ossSkipPadBytes(), do not call ossDecode() unless ossSkipPadBytes() returned successfully.
Used to check whether objHndl is a file handle, a socket handle, an address of a linked-list of OSAK buffers (DEC UNIX and VMS only), or a regular memory address.
One of the following values:
switch(ossTestObj(world, encodedData.value)) { case OSS_FILE: ossPrint(world, "This handle is a file handle."); break; case OSS_SOCKET: ossPrint(world, "This handle is a socket handle."); break; default: ossPrint(world, "This is a non-file/non-socket handle."); break; }
If ossTestObj() is called for the decoder's output value, it returns the enumerator OSS_FILE for values that are stored in temporary files, in accordance with the applied OSS.OBJHANDLE | OSS.NOCOPY directive.
The encoder or decoder uses the OssBuf structure to write or read the encoded data. The OssBufExtended structure allows the user to store and retrieve an initial buffer to start decoding from before starting to read data from a file or socket (can contain undecoded data from the last TCP/IP socket read by the decoder.
The functions described in this section are used for performing specialized tasks such as: conversions, copying or comparing ASN.1 messages, runtime manipulation of ASN. 1 Information Object Sets, handling multi-threading, backward compatibility, etc.
Enable you to manipulate Information Object Sets at run time, by adding an object to an extensible Information Object Set. The ossRemoveInfoObject() function removes the previously added object.
If successful, it returns zero. Otherwise, it returns a non-zero value.
TCIP_CLASS newInfoObj; ObjectSetEntry *myObjSet; OssEncodedOID encodedOID; . . . newInfoObj.Type=2; newInfoObj.description = malloc(16*sizeof(char)); strcpy(newInfoObj.description, "A new Info Obj."); encodedOID.value = NULL; encodedOID.length = 0; ossAsnValToEncodedOid(&world, "{0 4}", &encodedOID); . . . newInfoObj.id.length = encodedOID.length; newInfoObj.id.value = encodedOID.value; ossAddInfoObject(world, TCIP_ObjSet_OSET, &newInfoObj); . . . ossRemoveInfoObject(world, TCIP_ObjSet_OSET, &newInfoObj); free(newInfoObj.description); ossPrint(world, "After removal, set looks like:\n"); myObjSet = ossGetInfoObjectSet(world, TCIP_ObjSet_OSET); while(myObjSet != NULL) { /* print out address and description for each element in set */ myInfoObj = (TCIP_CLASS *)myObjSet->object; ossPrint(world, "ObjSet @%d, %s\n", myObjSet->object, myInfoObj->description); myObjSet = myObjSet->next; } ossFreeBuf(world, encodedOID.value);
You cannot use the ossRemoveInfoObject() function to remove Information Objects defined in your ASN.1 schema. To remove them, modify your ASN.1 specifications and recompile. However, you can use ossRemoveInfoObject() to remove dynamically added Information Objects.
To free memory associated with Information Objects, use ossterm() | ossWterm(), unless you have explicitly allocated memory (through malloc()).
To use TOED with Information Object handling functions, ASN.1-compile your schema with the -autoEncDec and -toed compiler options.
To make these functions available at run time, C-compile the generated code file with -DOSS_INFOOBJ_API.
These functions convert the value of an OBJECT IDENTIFIER or a RELATIVE-OID, respectively, from a string to the ENCODED C-representation structure, which is required before passing Object Identifiers to the encoder. The C-representation structure is defined as follows:
typedef struct { unsigned short length; unsigned char *value; } OssEncodedOID;
value is a pointer to a byte array containing the encoded data, as BER value, without tag and length:
OBJECT IDENTIFIER "{1 2 3 4 5}" converted to: 0x2A, 0x03, 0x04, 0x05
length is the size of the array in bytes: 4, in this case.
If successful, it returns zero. Otherwise, it returns a non-zero value.
OssGlobal world; OssBuf encodedData; OssEncodedOID encodedOID; ObjectID OIDvalue; int rc, pdunum = 1; cchar *asnValue = "{1 2 3 418446744073709551615 456}"; . . . encodedOID.value = NULL; encodedOID.length = 0; ossAsnValToEncodedOid(&world, asnValue, &encodedOID); OIDvalue.length = encodedOID.length; OIDvalue.value = encodedOID.value; ossEncode(&world, pdunum, &OIDvalue, &encodedData);
The ossBinary2AVN() and ossAVN2Binary() functions enable conversion between the standard ASN.1 binary encoding rules (BER, CER, DER, PER, CPER, OER, and COER) and the AVN encoding rules.
To allow the OSS Nokalva runtime to automatically allocate and determine the length of the space required for the output, you can set the value field of avnTarget to NULL and the length field to 0 before calling this function. To free up the automatically allocated memory when it is no longer needed, you can call ossFreeBuf() for the avnTarget.value field.
To allow the OSS Nokalva runtime to automatically allocate and determine the length of the space required for the output, you can set the value field of binTarget to NULL and the length field to 0 before calling this function. To free up the automatically allocated memory when it is no longer needed, you can call ossFreeBuf() for the binTarget.value field.
Alternatively, you can preallocate your own memory buffer for the output and set the value field to reference it and the length field to contain the length in bytes of the allocated buffer. To free up the used memory when it is no longer needed, you should call your standard memory deallocation function.
The ossBinary2AVN() and ossAVN2Binary() functions perform conversion by decoding and then re-encoding the input message. The functions check if, at decoding stage, an open type or contents constrained type is left undecoded. This is possible when component relation constraints cannot be resolved for an extensible open type, when the OSS.NoConstrain compiler directive is applied to an open or contents constrained type, or when you use the TOED library without specifying the -autoencdec and -constraints options at ASN.1 compile time. Such an undecoded type cannot be converted. In this case, the functions issue the D0373S error and return the CONVERSION_NOT_POSSIBLE code.
The ossBinary2AVN() and ossAVN2Binary() functions return an integer. If the input was successfully converted, a value of zero is returned; otherwise, a non-zero value is returned.
Support for ASN.1 Value Notation encoding rules is a chargeable feature in the time-optimized encoder/decoder of non-evaluation licenses. Contact Sales to obtain pricing information.
The ossBinary2JSON() and ossJSON2Binary() functions enable conversion between the standard ASN.1 binary encoding rules (BER, CER, DER, PER, CPER, OER, and COER) and the JSON encoding rules.
The ossBinary2JSON() and ossJSON2Binary() functions return an integer. If the input was successfully converted, a value of zero is returned; otherwise, a non-zero value is returned.
The ossBinary2JSON() and ossJSON2Binary() functions are available since version 10.3.
Checks whether the caller of the current function is ossDecode() or ossEncode(). This function must be called either from a custom memory manager or by the callback function associated with a user-defined subtype constraint.
When the caller is ossDecode(), the function returns a non-zero value. When the caller is ossEncode(), it returns zero.
if(ossCallerIsDecoder(world)) { /* allocate memory for decoded structure */ . . . . } else { /* allocate memory for encoding */ . . . . }
Converts a time_t standard ANSI type value into a GeneralizedTime or UTCTime ASN.1 value notation format, respectively.
If successful, it returns zero. Otherwise, it returns one of these values: BAD_ARG, BAD_TIME, OUT_MEMORY.
Note that error checking is omitted for clarity:
OssGlobal w, *world = &w; int ret; time_t tt; GeneralizedTime gt, *pgt = > char *str = "20040301112548.25-0600", *pbuf = NULL; . . . ossPrint(world, "GeneralizedTime string: %s\n", str); ossGenTimeStringToCalTime(world, str, &tt); ossPrint(world, "Calendar time: %d\n", tt); ossCalTimeToGenTimeStruct(world, tt, -360, &pgt); ossPrint(world, "GenneralizedTime struct:\n" " year: %d\n month: %d\n day: %d\n" " hour: %d\n minute: %d\n second: %d\n millisec: %d\n" " mindiff: %d\n utc: %d\n", pgt->year, pgt->month, pgt->day, pgt->hour, pgt->minute, pgt->second, pgt->millisec, pgt->mindiff, pgt->utc); ossGenTimeStructToCalTime(world, pgt, &tt); ossPrint(world, "Calendar time: %d\n", tt); ossCalTimeToGenTimeString(world, tt, -360, &pbuf); ossPrint(world, "GenneralizedTime string: %s\n", pbuf); ossFreeMemory(world, pbuf);
Output:
GeneralizedTime string: 20040301112548.25-0600 Calendar time: 1078161948 GenneralizedTime struct: year: 2004 month: 3 day: 1 hour: 11 minute: 25 second: 48 millisec: 0 mindiff: -360 utc: 0 Calendar time: 1078161948 GenneralizedTime string: 20040301112548-0600
Converts a time_t standard ANSI type value into a GeneralizedTime or UTCTime value, respectively.
If successful, it returns zero. Otherwise, it returns one of these values: BAD_ARG, BAD_TIME, OUT_MEMORY.
Checks whether schema constraints are satisfied in an unencoded PDU. By default, the encoder/decoder performs constraint checking, which can be disabled by the NOCONSTRAIN flag (through ossSetFlags()). This function allows you to check constraints on a type without calling the encoder/decoder.
If successful, it returns zero. Otherwise, it returns an error code.
OssGlobal w, *world = &w; OssBuf encodedData; MyASN1DataType myData; int rc; . . . if (rc = ossCheckConstraints(world, MyASN1DataType_PDU, &myData)) { ossPrint(world, "Constraint check failed: returncode = %d\n", rc); exit(1); } else { ossEncode(world, MyASN1DataType_PDU, &myData, &encodedData); }
To use the ossCheckConstraints() function with the TOED, compile your ASN.1 specification with the -constraints option specified. Note that not all constraints are supported for this function when linking with the TOED library, except for component relation constraints.
Compares two unencoded PDUs to check if their values are equal. The values are considered equal if their known components are equal. If there are no known components (for example, two CHOICE values with unrecognized extension additions (zero CHOICE selector)), they are considered equal.
If data structures are equal, returns zero. If they are not equal, returns 1. Otherwise, returns en error code:
OssGlobal w, *world = &w; OssBuf encodedData; MyASN1DataType myData1, myData2; . . . if(!ossCmpValue(world, MyASN1DataType_PDU, &myData1, &myData2) ossPrint(world, "Values are equal.\n");
This function cannot be used for types marked with the OSS.OBJHANDLE | OSS.NOCOPY directive that do not reside in plain memory.
To support this function, TOED builds must be C-compiled with the OSS_COMPARE_VALUE defined.
Converts a BCD string value into an OCTET STRING type value. The function was added in version 10.2.0.
The ossConvertBCDStringToOctet() function returns an integer. When conversion succeeds, a value of zero is returned. When either world, oct_str, or BCD_str is a NULL pointer, the function returns the BAD_ARG enumerator. When the input data contains invalid characters, a value of DATA_ERROR is returned. When ossGetMemory() cannot allocate memory for the output string, a value of OUT_MEMORY is returned.
OssGlobal w, *world = &w; char *bcd_str = "250961278"; unsigned char *buf = NULL; unsigned int os_len; int err; . . . . ossPrint(world, "Source BCD string: %s\n", bcd_str); ossPrint(world, "Call ossConvertBCDStringToOctet()... "); err = ossConvertBCDStringToOctet(world, bcd_str, strlen(bcd_str), &buf, &os_len); if (err == 0) { ossPrint(world, "conversion succeeded.\n"); ossPrint(world, "Resulting octet string: \n"); ossPrintHex(world, (char *)buf, os_len); ossFreeMemory(world, buf); } else { ossPrint(world, "conversion failed with return code %d\n", err); } . . . .
ossConvertBCDStringToOctet() sample output:
Source BCD string: 250961278 Call ossConvertBCDStringToOctet()... conversion succeeded. Resulting octet string: 25096127 8F
When oct_str points to NULL, the ossConvertBCDStringToOctet() function will automatically allocate space for the output string. When you preallocate memory for the output string, you must set the oct_str pointer to reference the beginning of your memory block.
When you use the ossConvertBCDStringToOctet() function to allocate memory, you must call the ossFreeMemory() function and pass the returned oct_str pointer to it when your application no longer needs the output string. If you allocated memory for the output string, be sure to deallocate it when the memory is no longer needed.
Converts an OCTET STRING type value into a BCD string value. The function was added in version 10.2.0.
The ossConvertOctetToBCDString() function returns an integer. When conversion succeeds, a value of zero is returned. When either world, oct_str or BCD_str is a NULL pointer, the function returns the BAD_ARG enumerator. When the input string contains a nibble whose value is in the range 0xA - 0xE, or, when the nibble is set to 0xF (the filler nibble), but it is not the last one within the string, a value of DATA_ERROR is returned. When ossGetMemory() cannot allocate memory for the output string, a value of OUT_MEMORY is returned.
OssGlobal w, *world = &w; unsigned char os_val[] = { 0x25, 0x09, 0x61, 0x27, 0x8F }; unsigned int os_len = sizeof(os_val); char *buf = NULL; int err; . . . . ossPrint(world, "Source octet string: "); ossPrintHex(world, (char *)os_val, os_len); ossPrint(world, "Call ossConvertOctetToBCDString()... "); err = ossConvertOctetToBCDString(world, os_val, os_len, &buf); if (err == 0) { ossPrint(world, "conversion succeeded.\n"); ossPrint(world, "Resulting BCD string: %s\n", buf); ossFreeMemory(world, buf); } else { ossPrint(world, "conversion failed with return code %d\n", err); } . . . .
ossConvertOctetToBCDString() sample output:
Source octet string: 25096127 8F Call ossConvertOctetToBCDString()... conversion succeeded. Resulting BCD string: 250961278
If BCD_str points to NULL, the function will automatically allocate the space for the output string. When you preallocate memory for the output string, you must set the BCD_str pointer to reference the beginning of your memory block.
When you use the ossConvertOctetToBCDString() function to allocate memory, you must call the ossFreeMemory() function and pass the returned BCD_str pointer to it when your application no longer needs the output string. If you allocate memory for the output string, be sure to deallocate it when the memory is no longer needed.
Converts an OCTET STRING type value into a TBCD string value. The function was added in version 10.2.0.
The ossConvertOctetToTBCDString() function returns an integer. When conversion succeeds, a value of zero is returned. When either world, oct_str, or TBCD_str is a NULL pointer, the function returns the BAD_ARG enumerator. When the filler 0xF is present in the input string but is not the last nibble, a value of DATA_ERROR is returned. When ossGetMemory() cannot allocate memory for the output string, a value of OUT_MEMORY is returned.
OssGlobal w, *world = &w; unsigned char os_val[] = { 0x25, 0x09, 0xA1, 0x2C, 0xEF }; unsigned int os_len = sizeof(os_val); char *buf = NULL; int err; . . . . ossPrint(world, "Source octet string: "); ossPrintHex(world, (char *)os_val, os_len); ossPrint(world, "Call ossConvertOctetToTBCDString()... "); err = ossConvertOctetToTBCDString(world, os_val, os_len, &buf); if (err == 0) { ossPrint(world, "conversion succeeded.\n"); ossPrint(world, "Resulting TBCD string: %s\n", buf); ossFreeMemory(world, buf); } else { ossPrint(world, "conversion failed with return code %d\n", err); } . . . .
ossConvertOctetToTBCDString() sample output:
Source octet string: 2509A12C FE Call ossConvertOctetToTBCDString()... conversion succeeded. Resulting TBCD string: 52901*a2c
If TBCD_str points to NULL, the function will automatically allocate space for the output string. When you preallocate memory for the output string, you must set the TBCD_str pointer to reference the beginning of your memory block.
When you use the ossConvertOctetToTBCDString() function to allocate memory, you must call the ossFreeMemory() function and pass the returned TBCD_str pointer to it when your application no longer needs the output string. If you allocated memory for the output string, be sure to deallocate it when the memory is no longer needed.
Converts a null-terminated input string formatted as "'xx...xx'H" into a human-readable timestamp format, YYYYMMDDhhmmss[+-]hhmm.
If successful, it returns zero. Otherwise, it returns one of the following error codes:
When pstr_ts points to NULL, the function allocates memory for the output string.
ossConvertOctetToTimeStamp() converts the string '1507061432002B0600'H into output as follows:
20150706143200+0600
Converts a TBCD string value into an OCTET STRING type value. The function was added in version 10.2.0.
The ossConvertTBCDStringToOctet() function returns an integer. When conversion succeeds, a value of zero is returned. When either world, oct_str, or TBCD_str is a NULL pointer, the function returns the BAD_ARG enumerator. When the input data contains invalid characters, a value of DATA_ERROR is returned. When ossGetMemory() cannot allocate memory for the output string, a value of OUT_MEMORY is returned.
OssGlobal w, *world = &w; char *tbcd_str = "52901*a2c"; unsigned char *buf = NULL; unsigned int os_len; int err; . . . . ossPrint(world, "Source TBCD string: %s\n", tbcd_str); ossPrint(world, "Call ossConvertTBCDStringToOctet()... "); err = ossConvertTBCDStringToOctet(world, tbcd_str, strlen(tbcd_str), &buf, &os_len); if (err == 0) { ossPrint(world, "conversion succeeded.\n"); ossPrint(world, "Resulting octet string: \n"); ossPrintHex(world, (char *)buf, os_len); ossFreeMemory(world, buf); } else { ossPrint(world, "conversion failed with return code %d\n", err); } . . . .
ossConvertTBCDStringToOctet() sample output:
Source TBCD string: 52901*a2c Call ossConvertTBCDStringToOctet()... conversion succeeded. Resulting octet string: 2509A12C FE
If oct_str points to NULL, the function will automatically allocate space for the output string. When you preallocate memory for the output string, you must set the oct_str pointer to reference the beginning of your memory block.
When you use the ossConvertTBCDStringToOctet()function to allocate memory, you must call the ossFreeMemory() function and pass the returned oct_str pointer to it when your application no longer needs the output string. If you allocated memory for the output string, be sure to deallocate it when the memory is no longer needed.
Allocates memory and copies unencoded PDUs into identical structures. To deallocate the destination PDU after using it, use ossFreePDU().
If successful, it returns zero. Otherwise, it returns an error code:
OssGlobal w, *world = &w; MyASN1DataType *decodedData, *newValue=NULL; int rc; . . . ossCpyValue(world, MyASN1DataType_PDU, decodedData, &newValue); . . . ossFreePDU(world, MyASN1DataType_PDU, newValue);
To support this function, TOED builds must be C-compiled with the OSS_COPY_VALUE defined.
These functions convert an OBJECT IDENTIFIER or a RELATIVE-OID dotted notation string into the ENCODED format, which is required before passing Object Identifiers to the encoder. The dotted notation is a string of numbers separated by periods ("1.2.3.4.5").
The ENCODED representation has the following format:
typedef struct { unsigned short length; unsigned char *value; } OssEncodedOID;
value is a pointer to a byte array containing the encoded data, as BER value, without tag and length: OBJECT IDENTIFIER "1.2.3.4.5" is stored as: 0x2A, 0x03, 0x04, 0x05).
length is the size of the array in bytes: 4, in this case.
If successful, it returns zero. Otherwise, it returns a non-zero value.
OssGlobal world; OssBuf encodedData; OssEncodedOID encodedOID; ObjectID OIDvalue; int rc, pdunum = 1; char *dotValue = "1.2.3.418446744073709551615.456"; . . . encodedOID.value = NULL; encodedOID.length = 0; rc = ossDotValToEncodedOid(&world, dotValue, &encodedOID); if (rc) { ossPrint(world, "Call to ossDotValToEncodedOid() failed: %d\n", rc); return rc; } OIDvalue.length = encodedOID.length; OIDvalue.value = encodedOID.value; ossEncode(&world, pdunum, &OIDvalue, &encodedData);
Creates a copy of an instance of the OssGlobal structure initialized with the ossinit() | ossWinit() function.
A call to ossDupWorld() incurs a lower overhead compared to a new call to ossinit() | ossWinit(). When using this function in multi-threaded applications, you will not have to call ossinit() | ossWinit() for each new thread because the parent code calls it once. Then, each new thread calls ossDupWorld() upon start-up to obtain its own copy of OssGlobal. The duplicate copy of OssGlobal inherits encoding rules, encoding/decoding flags, and other runtime settings from the original. Before termination, each thread must call ossterm(), ossUterm(), ossWterm() to free the resources connected to its copy of the OssGlobal variable.
If successful, it returns zero. Otherwise, it returns a non-zero value.
Important: In the memory handle allocation mode, a call to ossDupWorld() does not preserve the currently installed memory handle in a copied world. This is done to avoid simultaneous write access to the handle when trying to allocate memory in different threads. To use memory handle allocation mode in a multithreading application, you must manually create different memory handles for each OSS global environment variable.
Warning: When using dynamically linked libraries (DLLs), make sure you do not call ossterm() | ossWterm() | ossUterm on the original instance of OssGlobal while using duplicate copies of the OssGlobal variable. Otherwise, DLLs that were loaded before the call to ossDupWorld() is unloaded from memory, causing the application to crash on any attempt of a copy of OssGlobal. Make sure you call ossterm() | ossUterm() | ossWterm() on the copied OssGlobal before it is called on the original OssGlobal variable.
These functions construct the string representation of an ISO 8601 [recurring] time interval in the form of a [recurring] duration-end pair from its individual components. Use them when the TIME type has a Property settings constraint applied, the Basic property is set to [Rec-]Interval and Interval-type is set to "DE".
For newly constructed time values, the ossGetTimeKind() function returns oss_tk_DurationEndPointRecInterval | oss_tk_DurationEndPointInterval .
If successful, it returns zero. Otherwise, it returns a non-zero value.
OssGlobal w, *world = &w; int rc, rec = 0; ossTimePoint end; ossDuration dur; char *result = NULL; . . . ossStringToDurationEndPointRecInterval(world, R/P1Y4M20D/1985-04-12T23:20:50", &dur, &end, &rec); dur.bit_mask |= OSS_de_hours_present; dur.hours = 1; dur.bit_mask |= OSS_de_minutes_present; dur.minutes = 30; rec = 2; dur.bit_mask &= ~OSS_de_years_present; ossDurationEndPointRecIntervalToString(world, &dur, &end, rec, &result); ossPrint(world, "Resulting string: %s\n", result); ossFreeBuf(world, result);
Prints:
Time interval to string conversion succeeded. Resulting string: R2/P4M20DT1H30M/1985-04-12T23:20:50
ossStringToDurationEndPointRecInterval() | ossStringToDurationEndPointInterval()
These functions construct the string representation of an ISO 8601 [recurring] time interval in the form of a duration from its individual components. Use them when the TIME type has a Property settings constraint applied, the Basic property is set to [Rec-]Interval and Interval type is set to "D".
For newly constructed time values, the ossGetTimeKind() function returns oss_tk_DurationRecInterval | oss_tk_DurationInterval .
If successful, it returns zero. Otherwise, it returns a non-zero value.
OssGlobal w, *world = &w; int rc, rec = 0; ossDuration dur; char *result = NULL; . . . rc = ossStringToDurationRecInterval(world, "R10/P1Y4M20DT30M", &dur, &rec); dur.bit_mask |= OSS_de_seconds_present; dur.seconds = 45; ossDurationRecIntervalToString(world, &dur, rec *2, &result); ossPrint(world, "Resulting string: %s\n", result); ossFreeBuf(world, result);
Prints:
Resulting string: R20/P1Y4M20DT30M45S
ossStringToDurationRecInterval() | ossStringToDurationInterval()
Converts data to binary, hexadecimal, and BASE64 formats. To convert data, specify the corresponding format identifiers: OSS_BIN_DATA, OSS_HEX_DATA, OSS_BASE64_DATA.
If the corresponding memory manager is in use, conversion is possible not only in memory but also to and from files, sockets and OSAK-buffers.
If successful, it returns zero. Otherwise, it returns a non-zero value.
/* OSS_BIN_DATA -> OSS_HEX_DATA conversion from file to memory */ OssGlobal w, *world = &w; OssBuf fromData; /* input data */ OssBuf toData; /* output data */ int retcode; if ((retcode = ossinit(world, control_table))) { ossPrint(NULL, "Ossinit() returned %d\n", retcode); return retcode; } #ifdef DLL_LINKAGE if (!ossLoadMemoryManager(world, OSS_FILE_MEMMGR, NULL)) { ossPrint(world, "Memory manager linkage failed.\n"); ossterm(world); return 1; } #endif /* DLL */ . . . /* Initialize the input buffer as a file */ fromData.value = (unsigned char *)ossMarkObj(world, OSS_FILE, (void *)"input.bin"); fromData.length = 0; /* conversion of all bytes from the file */ /* Initialize the output buffer as a dynamic memory */ toData.value = NULL; toData.length = 0; if (ossConvertData(world, &fromData, OSS_BIN_DATA, &toData, OSS_HEX_DATA)) { /* an error occurred, print errmsg */ ossPrint(world, "%s\n", ossGetErrMsg(world)); ossterm(world); /* Free up allocated resources */ return 1; } ossUnmarkObj(world, fromData.value); . . . /* Free up the allocated data buffer */ ossFreeBuf(world, toData.value); . . . ossterm(world);
If the input format is OSS_HEX_DATA or OSS_BASE64_DATA, the input data is checked for conformance to the format, and whitespace is ignored. If the number of digits in the input hexadecimal data is odd, a trailing '0' is added by default. For example, 'FF F' is treated as 'FF F0'.
Converts GeneralizedTime or UTCTime from ASN.1 value string into a time_t standard ANSI type (calendar time) value.
If successful, it returns zero. Otherwise, it returns a non-zero value.
See ossCalTimeToGenTimeString().
Converts a GeneralizedTime or UTCTime value into a time_t standard ANSI type (UTC calendar time value).
If successful, it returns zero. Otherwise, it returns BAD_ARG or BAD_TIME.
See ossCalTimeToGenTimeString()
These functions convert an OBJECT IDENTIFIER or a RELATIVE-OID value from the ENCODED representation into the value notation representation. They are especially useful for printing Object Identifier values received from the decoder. The value notation form is a string of whitespace-separated numbers enclosed in braces (for example, a RELATIVE-OID can be represented as "{3 4 5}").
The ENCODED representation has the following format:
typedef struct { unsigned short length; unsigned char *value; } OssEncodedOID;
value is a pointer to a byte array containing the encoded data, as BER value, without tag and length, for example, RELATIVE-OID "{3 4 5}" is stored as: 0x03, 0x04, 0x05).
length is the size of the array in bytes: 3, in this case.
If successful, it returns zero. Otherwise, it returns a non-zero value.
OssGlobal w; OssBuf encodedData; OssBuf myAsnValOid; Msg *decodedData = NULL; . . . ossDecode(&w, &myPduNum, &encodedData, (void **)&decodedData); myAsnValOid.value = NULL; myAsnValOid.length = 0; ossEncodedRelOidToAsnVal(&w, (OssEncodedOID*)&decodedData->tcpId, &myAsnValOid); ossPrint(&w, "AsnVal: %s\n", myAsnValOid.value); . . . ossFreeBuf(&w, myAsnValOid.value);
These functions convert an OBJECT IDENTIFIER or a RELATIVE-OID value from the ENCODED representation into the dotted notation. They are especially useful when printing Object Identifier values received from the decoder. The dotted notation is a string of numbers separated by periods (for example, a RELATIVE_OID can be represented as "3.4.5").
The ENCODED representation has the following format:
typedef struct { unsigned short length; unsigned char *value; } OssEncodedOID;
value is a pointer to a byte array containing the encoded data, as BER value, without tag and length, for example, RELATIVE-OID "3.4.5" is stored as: 0x03, 0x04, 0x05)
length is the size of the array in bytes: 3, in this case.
If successful, it returns zero. Otherwise, it returns a non-zero value.
These functions parse the input time represented as ASN.1 value string to retrieve the field values of a GeneralizedTime or UTCTime type.
If successful, it returns zero. Otherwise, it returns BAD_TIME. If the UTC time format is not enabled while using DER encoding rules, it returns BAD_TIME.
UTCTime myTime; OssGlobal w, *world = &w; char gen_timeString[40]; unsigned short fraction_precision=0; unsigned int fraction, year, month, day, hour, minute, second; int mindiff; . . . myTime.year=2001; myTime.month=8; myTime.day = 23; myTime.hour = 12; myTime.minute = 33; myTime.second=27; myTime.mindiff = -300; ossIntsToGeneralizedTime(world, myTime.year, myTime.month, myTime.day, myTime.hour, myTime.minute, myTime.second, 258, 3, 1, gen_timeString); ossPrint(world, "Generalized TimeString: %s \n",gen_timeString); ossGeneralizedTimeToInts(world, gen_timeString, &year, &month, &day, &hour, &minute, &second, &fraction, &fraction_precision, &mindiff); ossPrint(world, "Year: %d\nMonth: %d\nDay: %d\nHour: %d\nMinute: %d\n\ Second: %d\nMindiff: %d\nFraction: %d\nFraction_Prec: %d\nReturn code: %d\n", year, month, day, hour, minute, second, mindiff, fraction, fraction_precision, retcode);
Prints
Generalized TimeString: 20010823123327.258Z Year: 2001 Month: 8 Day: 23 Hour: 12 Minute: 33 Second: 27 Mindiff: 1 Fraction: 258 Fraction_Prec: 3 Return code: 0
These functions are implemented in SOED (for example, soeddefa.lib).
ossIntsToGeneralizedTime() | ossIntsToUTCTime()
Performs the partial decoding. For general information about partial decoding, see the Partial Decoding section.
If NULL or the address of a NULL pointer is passed as the fourth argument, the decoder's memory manager will automatically allocate enough memory to hold the decoder data. On the other hand, if you preallocate a buffer for the decoder data and pass the address of a pointer that references your preallocated buffer, the decoder uses the provided buffer and works faster. Note, however, that after preallocating an output buffer and before calling the decoder each time, you must call the ossSetDecodingLength() function to set the length of the allocated buffer.
If a decoding error occurs and the decoding buffer was preallocated, the fields of the preallocated output area could be updated, therefore the contents are unpredictable. However, if you instructed the decoder to allocate the memory for the output data (by passing an address to a NULL pointer as a fourth parameter), the decoder removes any temporary memory allocated before exiting and its output will still point to the NULL pointer.
The ossPartialDecode() function returns an integer. If the input was successfully decoded, a value of zero is returned; otherwise, a non-zero value is returned. For more information about the return codes, see the ASN.1/C API Return Codes section. Upon failure, use the ossGetErrMsg() function to determine the cause of the problem.
During partial decoding, when the ossPartialDecode() function encounters a field to which the OSS.DataCallback or OSS.InfoCallback compiler directive is applied, it calls the specified callback function (provided by the user).
NOTE: The prototypes of the callback functions are incorporated into the generated header file.
Here is the data callback function prototype:
int my_callback(OssGlobal *world, long offset, long length, unsigned int flags, Tvalue *value);
The world, offset, length, and flags parameters are the same for all callback functions. The value parameter points to the decoded value of the field to which the directive is applied. Its C-type varies depending on the ASN.1 type and the C representation of the field.
Value | Description |
---|---|
OSS_ENCODING_UNDEFINED |
Is returned whenever the field in question is encoded using bit-oriented rules (PER, UPER, CPER, CUPER), and not octet-oriented rules (BER, DER, OER, COER). This is of consequence if you intend to modify values in-place, since offset and length alone will not isolate the value. Modifying the value when this flag is returned is not recommended. |
OSS_COMPLEX_ENCODING |
Is returned whenever a BER field is fragmented. Some types, for example, OCTET STRINGs, may be broken into fragments where each fragment has a separate offset and length. This makes it difficult to discern what the value is, and so modifying the value when this flag is returned is not recommended. |
To instruct the decoder whether to stop or continue decoding the message, use one of the return codes of your callback function.
Any other return code from the callback function signals to the decoder a decoding error, in which case the decoder executes a longjmp() and ossPartialDecode() returns the return code it received from the callback function. However, returning via longjmp() is often slower than using OSS_SKIP_TO_PDU_END to skip to the end.
--<OSS.DataCallback BCAS.BBCard.age "myFunc">-- BCAS DEFINITIONS ::= BEGIN CareerEntry ::= SEQUENCE { from INTEGER (0..MAX), to INTEGER (0..MAX) OPTIONAL, team VisibleString (SIZE (1..255)) } BBCard ::= SEQUENCE { name VisibleString (SIZE(1..64)), age INTEGER (1..100), position VisibleString (SIZE (1..64)), career SEQUENCE OF CareerEntry } END
The compiler generates the following callback function prototype:
/* myFunc is user-defined data callback function for ASN.1 item(s) * BCAS.BBCard.age */ extern int myFunc(OssGlobal *_g, long offset, long length, unsigned int flags, unsigned short * value);
The decoded value pointed to by the last parameter is available only in the callback function.
The decoder reuses the memory allocated for the value after the callback function returns. Therefore, the callback function code should store the decoded field value for future use, if necessary. Reusing memory like this significantly reduces the amount needed for decoding. For example, if the DataCallback directive is applied to an element of a SEQUENCE OF type, the decoder will not allocate more memory than needed for one element. Decoding speed is improved if you use a preallocated buffer for partial decoding.
Here is the info callback function prototype:
int my_callback(OssGlobal *world, char * fname, unsigned int flags);
The return codes are the same as the ones for the data callback functions.
To pass data between the application and the callback functions or between callback functions calls, use the userVar (void *) field within the ossGlobal structure. If the data to be passed fits the pointer size, it can be directly stored in the field. Otherwise, the field can store a pointer to the memory block that contains the data.
When the OSS.DataCallback directive is applied to a field, the compiler generates code that fully decodes the field, and it passes the address of the decoded value to the specified callback function. Otherwise, the compiler generates code to skip the field.
The method used for skipping a field depends upon the field and upon the encoding rules employed, as follows:
In any case, the pointer to the current position is advanced to the subsequent field.
NOTE: During partial decoding, when the decoder is able to skip a field by jumping over it, it does not check the field encoding for adherence to the encoding rules.
Sets or gets backward compatibility flags that affect the behavior of the ossEncode() and ossDecode() functions.
NOTE: OSS does not guarantee compatibility between different versions of the ASN.1 Tools released more than 10 years apart.
Flag | Description |
---|---|
OSS_ADD_ZERO_SECONDS_TO_XML_ENCODING_OF_NULLTERM_TIME (E) |
Available for the LEAN/SOED/TOED XER and LEAN/TOED E-XER encoders. Forces the encoder to display a zero seconds component when encoding GeneralizedTime and UTCTime type values that have the NULLTERM representation. |
OSS_ALLOW_ABSENT_OR_BAD_SECONDS |
Available for CER/DER SOED and DER TOED decoders. Instructs the decoder to restore old behavior, and accept non-standard encodings. Starting with version 8.1.2, the decoder reports an error if the encoding of a UTCTime or GeneralizedTime type does not satisfy the restrictions on BER employed by both CER and DER. For example, when seconds digits are absent, or trailing zeroes are present in a fractional part. |
OSS_ALLOW_MISPLACED_EXTENSION_FIELDS |
Available for the SOED/LED BER decoder. Instructs the decoder in relaySafe mode to accept an unknown extension field, placed after the additional root fields in the input encoding. Otherwise, the decoder issues the error message "D0047E: Tag not recognized". |
OSS_ALLOW_NON_NR3_DER_REAL |
Available for the DER, CER and PER encoder. Instructs the encoder to skip NR3 normalization of decimal REAL type values. |
OSS_ALLOW_NULL_IN_TIME |
Available for the BER Time-optimized decoder. The ossDecode() function will silently ignore superfluous trailing NULL octets in the encoding of a value of a GeneralizedTime type with the NULLTERM representation. Otherwise, an error is issued. |
OSS_ALLOW_TIME_DIFFERENTIAL_IN_UTC_TIME |
Available for the DER encoder. UTCTime values that are incorrectly encoded (with a non-zero time differential) will be successfully decoded. |
OSS_ALLOW_ZERO_LENGTH_EXTENSIONS |
Available for the PER decoder version 6.1.3. The ossDecode() function will silently ignore zero-length extension fields in a PER encoding. Starting with version 6.1.4, unless STRICT_ENCODING_DECODING_RULES is specified (via ossSetDecodingFlags() or ossSetFlags()), the ossDecode() function silently ignores zero-length extension fields. Otherwise, the ossDecode() function issues an error when processing PER encodings with zero-length extension fields. |
OSS_ALLOW_ZERO_LENGTH_OPENTYPE_STRINGS |
Available for PER SOED. Instructs the decoder to restore old behavior and accept non-standard encodings in which extension additions are encoded as zero-length opentype values. Starting with version 4.2, unless the extension addition is a NULL type, the encoder reports an error when the encoding of an extension addition occupies 0 bits. |
OSS_AUTO_DETECT_PDU_NUMBER |
Available for the SOED runtime. Instructs the decoder to restore the previous behavior and attempt to determine the PDU number even when a non-zero number is passed. Starting with version 10.2, the SOED BER decoder attempts to determine the PDU number from the input encoding only if the zero PDU number was passed to ossDecode(). Note: If -compat autoDetectPDUnumber is specified, the flag is automatically enabled in the generated code. |
OSS_EXTENDED_RESTRICTED_KMC_STRING_AS_OCTETS |
Available for the PER encoder/decoder. Instructs the encoder/decoder to ignore Permitted Alphabet in extensible KMC string types when the string length exceeds that of the extension root. |
OSS_EXTENDED_UNRESTRICTED_CHAR_STRINGS |
Available for the PER encoder. Instructs the encoder to encode length determinants (of unknown multiplier character strings with size constraints) as constrained INTEGERs. Also, the character strings are encoded as values of extensible types (if the extension marker "..." is used in the ASN.1 syntax). |
OSS_INTERVAL_FRACTION_1_999 |
Available for the PER runtime. The use of this flag causes the encoding of a DURATION-INTERVAL/fractionial value as INTEGER (1..999, ..., 1000..MAX) instead of INTEGER (0..999, ..., 1000..MAX). |
OSS_KEEP_MEMORY_MANAGER_TEMPORARY_FILES |
Available for socket and file memory managers. Instructs socket and file memory managers to delete temporary files automatically created for marked objects only if ossFreePDU() is called for the PDU stored in each file. Starting with version 8.3, these files are deleted when ossterm() is called. |
OSS_NO_DETAIL_MM_ERROR_CODES |
Available for the SOED runtime. Prior to version 10.0, when errors occurred in the OSS Socket and File Memory Managers, OSS API functions returned the common error code FATAL_ERROR (18) and the following message: x0087S: Undefined memory-management error #N. Starting with version 10.0, more error codes and messages are returned in this case. This flag restores the previous behavior. |
OSS_OLD_UTF8_CHECK |
Available for the LEAN/SOED/TOED runtime. Starting with version 10.6, the runtimes check UTF8 characters more thoroughly: the high and low surrogate halves used by UTF-16 (U+D800 through U+DFFF) and code points that are not encodable by UTF-16 (those following U+10FFFF) are considered illegal Unicode values, and their UTF-8 encoding is treated as an invalid byte sequence. The 0xfffe and 0xffff UTF-8 encoding codes are also treated as an invalid byte sequence. This flag restores pre-10.6 runtime behavior. |
OSS_PACK_WIDE_STRINGS |
Available for PER. Wide string characters with permitted alphabet constraints are encoded relative to the zero value of the lowest Cell in the permitted alphabet and not to the lowest value in the Cell. For example:
A ::= BMPString (FROM({0,0,30,32}..{0,0,30,127})) a A ::= {0,0,30,64}Value a is encoded as 0x0140 instead of 0x0120 in aligned PER, as for the permitted alphabet: FROM({0,0,30,0}..{0,0,30,127} |
OSS_PER_ALLOW_TRAILING_ZEROS |
Available for PER SOED. Provides compatibility with pre-8.5 versions. Starting with version 8.5, the encoder strips zero trailing bits from the encoding of a BITSTRING with named bits according to Clause 16.2 of X.691. Previously, such bits were encoded. |
OSS_PER_NULLTERM_TIME_8BIT_CHARS |
Available for the PER encoder/decoder. Instructs the encoder/decoder to treat the Unaligned PER encoding of UTCTime and GeneralizedTime types in the NULLTERM C-representation as using 8 bits per character, the same as the Aligned PER encoding. |
OSS_PER_VISIBLE_EXCEPTIONS |
Available for the PER encoder/decoder. Instructs the encoder/decoder to treat the EXCEPT constraint as PER-visible. |
OSS_TRUNCATE_0_SECONDS_FROM_GENERALIZED_TIME |
Available for the SOED BER, DER, CER, and PER encoder. Trailing zeros placed after the seconds field in GeneralizedTime type encodings is truncated (for example, 1998120311235500 is truncated to 19981293112355). |
OSS_TRUNCATE_0_SECONDS_FROM_UTC_TIME |
Available for SOED BER, DER, CER, and PER encoder. Trailing zeros placed after the seconds field in UTCTime type encodings are truncated (for example, 98120311235500Z is truncated to 981203112355Z). |
OSS_USE_TYPE_IDENTIFICATION_ATTRIBUTE_FOR_UNION |
Available for the SOED/LED runtime. Starting with version 9.0, the OSS SOED/LED E-XER encoders no longer generate a type identification attribute for a CHOICE type with a USE-UNION encoding instruction when the final UNTAGGED encoding instruction is applied to the type. This flag instructs the E-XER encoder to restore the previous behavior. |
OSS_V412_TIME_AND_WIDE_CHAR_STRINGS |
Available for the PER encoder/decoder. The following changes take place:
|
OSS_V85_TABLE_CONSTRAINT_FOR_EXTENSIBLE_OBJECT_SETS |
Available for the SOED/LED runtime. Starting with version 8.6, the OSS Constraint Checker no longer mishandles table/component relation constraint violations for extensible object sets. The OSS ASN.1 compiler and the OSS runtime support X.681 Annex E.2. That is, constraint violation errors are reported if table/component relation constraints are not satisfied for extensible object sets, and in any of the following situations:
|
OSS_V90_ARRAY_AND_VARYING_SIZE |
Available for the SOED runtime. Prior to version 10.0, memory for the decoded values of:
In header files, such types are defined using a fixed size array, as illustrated below: S ::= IA5String (SIZE(0..10)) --<VARYING>-- typedef struct S { unsigned short length; char value[10]; } S;For example, the value field of the decoded values S ::= "foo" contained 3 bytes, instead of 10. This flag instructs the SOED decoders to restore the previous (pre-10.0) SOED decoder behavior. |
If ossSetCompatibilityFlags() is successful, returns zero. Otherwise, returns a non-zero value.
If ossGetCompatibilityFlags() is successful, returns a logical OR of the set compatibility flags. Otherwise, returns a value of -1.
OssGlobal w, *world = &w; unsigned long compatFlags; . . . compatFlags = OSS_EXTENDED_UNRESTRICTED_CHAR_STRINGS; compatFlags |= OSS_ALLOW_TIME_DIFFERENTIAL_IN_UTC_TIME; ossSetCompatibilityFlags(world, compatFlags); compatFlags = ossGetCompatibilityFlags(world); if(compatFlags & OSS_EXTENDED_UNRESTRICTED_CHAR_STRINGS) ossPrint(world, "Extended Unrestricted Char Strings in use.\n");
Sets or gets a definite limit on the number of levels of nesting a constructed string encoding can have. This limit helps prevent intentional or unintentional nested overloading of constructed string encodings.
If ossGetConstructedNestingLimit() is successful, returns the nesting level limit of constructed string encodings. Otherwise, returns -1.
If ossSetConstructedNestingLimit() is successful, returns 0. Otherwise, returns a non-zero error.
ossSetSeqSetNestingLimit() | ossGetSeqSetNestingLimit()
Retrieves the encodings of extension addition elements via their index contained in the ossExtensions structure upon decoding a PDU with unrecognized extensions. The ossExtensions structure is generated in the representation of SET or SEQUENCE types when the relaySafe option is specified.
If successful, it returns zero. Otherwise, it returns a non-zero value.
OssGlobal world; OssBuf encodedData, extBuf; Msg *decodedDataPtr = NULL; . . . ossDecode(world, &myPduNum, &encodedData, (void **)&decodedDataPtr); . . . ossGetExtensionAddition(world, decodedDataPtr->ossUnknownExt, 2, &extBuf); . . .
Returns the address of the specified Information Object in an Information Object Set, allowing you to analyze the contents of the object. You can determine the type of value contained in the open type by viewing the OBJECT IDENTIFIER field in the information object. This function is especially useful when you manually decode open types associated with Information Objects. However, using AUTOMATIC_ENCDEC encoder/decoder flag you will not have to manually retrieve open types when encoding and decoding, because they are automatically encoded/decoded with their containing type.
If successful, it returns the address of the specified object. Otherwise, it returns a NULL pointer.
TCIP_CLASS *myInfoObj; myInfoObj = ossGetInfoObject(world, TCIP_ObjSet_OSET, &cpt_ActivationTime_ID); ossPrint(world, "Type=%d, Descr=%s\n", myInfoObj->Type, myInfoObj->description);
When you use TOED with Information Object handling functions, ASN.1-compile your schema with the -autoEncDec and -toed compiler options. Also, to make these functions available at run time, C-compile the generated code file with -DOSS_INFOOBJ_API defined.
Note that for the automatic encoding/decoding of open types with TOED, you cannot use SET OF or SEQUENCE OF types to be referenced by a component relation constraint that is used to determine the base type of the open type.
Provides access to an Information Object Set when its identification number is given. Once you have retrieved a set, you can traverse it to access all of the contained objects. An Information Object Set is represented as doubly-linked list with each element having the following structure:
typedef struct ObjectSetEntry { struct ObjectSetEntry *next; void *object; struct ObjectSetEntry *prev; } ObjectSetEntry;
This function returns the first element in the double linked list. To traverse the list, use the next and prev pointers. The prev pointer of the first element is set to NULL and the next pointer of the last element is also set to NULL.
If successful, it returns the address of the first element. Otherwise, it returns a NULL pointer.
TCIP_CLASS *myInfoObj; ObjectSetEntry *myObjSet; . . . myObjSet = ossGetInfoObjectSet(world, TCIP_ObjSet_OSET); while(myObjSet != NULL) { myInfoObj = (TCIP_CLASS *)myObjSet->object; ossPrint(world, "Obj Set at: %d, description: %s\n", myObjSet->object, myInfoObj->description); myObjSet = myObjSet->next; }
To continue traverse the object set, call ossGetInfoObjectSet() every time after you add or delete objects.
To use TOED with Information Object handling functions, ASN.1-compile your schema with the -autoEncDec and -toed compiler options. To make these functions available at runtime, C-compile the generated code file with -DOSS_INFOOBJ_API defined.
Returns the number of bytes occupied by the OssGlobal structure.
You can also obtain the size of the OssGlobal structure using the C sizeof() function. However, the ossGetOssGlobalSize() function ensures that the size returned at runtime matches the size during build time.
Sets or gets the indentation level which the ossPrintPER() function will use to print out its output.
OssGlobal w, *world = &w; . . . ossSetPrintIndent(world, ossGetPrintIndent(wolrd) + 2); ossPrintPER(world, &pdunum, &encodedData, NULL, 0, NULL);
Sets or gets the current compatibility mode of SOED. The encoder/decoder simulates the behavior of the specified version. By default, the encoder/decoder emulates the behavior of the current version (OSS_CURRENT_VERSION is implied).
Value | Description |
---|---|
OSS_CURRENT_VERSION |
Instructs the encoder/decoder to use the current version compatibility mode. This is the default version and includes no compatibility flags. |
OSS_VERSION_412 |
Provides compatibility with pre-4.1.3 encoder/decoder. The enumerator includes the OSS_V412_TIME_AND_WIDE_CHAR_STRINGS compatibility flag. |
OSS_VERSION_419 |
Provides compatibility with pre-4.1.10 encoder/decoder. The enumerator includes the following compatibility flags:
|
OSS_VERSION_540 |
Provides compatibility with the pre-6.0 encoder/decoder. The enumerator includes the OSS_ALLOW_NULL_IN_TIME compatibility flag and all flags below. |
OSS_VERSION_811 |
Provides compatibility with the pre-8.1.2 encoder/decoder. The enumerator includes the OSS_ALLOW_ABSENT_OR_BAD_SECONDS compatibility flag and all flags below. |
OSS_VERSION_840 |
Provides compatibility with the pre-9.0 encoder/decoder. The enumerator includes the OSS_PER_ALLOW_TRAILING_ZEROS compatibility flag. |
OssGlobal w, *world = &w; OssRuntimeVersion rtVersion; . . . ossSetRuntimeVersion(world, OSS_VERSION_412); . . . rtVersion = ossGetRuntimeVersion(world);
If ossGetRuntimeVersion() returns OSS_CUSTOM_COMPATIBILITY, it means that the encoder/decoder works in a customized compatibility mode of OSS compatibility flags.
Sets or gets the definite limit for a SEQUENCE, SET, SEQUENCE OF, SET OF, or CHOICE encoding, regarding the number of levels of nesting. It prevents intentional or unintentional nested overloading of complex structured encodings.
If ossGetSeqSetNestingLimit() is successful, returns the nesting level limit. Otherwise, returns -1.
If ossSetSeqSetNestingLimit() is successful, returns zero. Otherwise, returns a non-zero error.
ossGetConstructedNestingLimit() | ossSetConstructedNestingLimit()
Extracts and returns the time kind from a string containing the ISO 8601 time value.
Returns an ossTimeKind enumeration.
OssGlobal w, *world = &w; int rc; ossTimePoint tp; char *value = "2007-01-04T13:40", *result = NULL; . . . switch(ossGetTimeKind(world, value)) { case oss_tk_TimePoint: ossStringToTimePoint(world, value, &tp); tp.bit_mask |= OSS_tp_time_diff_present; tp.time_diff.hours = 6; ossTimePointToString(world, &tp, &result); ossPrint(world, "Resulting string: %s\n", result); ossFreeBuf(world, result); break; case oss_tk_BadTime: ossPrint(world, "Bad time value.\n"); break; default: ossPrint(world, "Unexpected time value.\n"); }
Prints:
Resulting string: 2007-01-04T13:40+06
Sets or gets the user-defined functions for copying or comparing the userField field of the OpenType structure. These functions are automatically called by ossCpyValue() | ossCmpValue() after all open type fields are copied or compared. To disable these calls, call ossSetUserFieldCpyCmp() with the NULL passed for either or both function arguments.
The user-defined copy and compare functions have the following prototypes:
int (CDECL_ENTRY_FPTR *ossUserFieldCpy)(OssGlobal *world, OpenType *src, OpenType *dest); int (CDECL_ENTRY_FPTR *ossUserFieldCmp)(OssGlobal *world, OpenType *data1, OpenType *data2);
src is the open type source value.
dest is the open type destination value.
When you call the function (*ossUserFieldCpy)(), the open type field userField can be processed according to your specific needs.
If successful, it returns zero. Otherwise, it returns a non-zero value.
If the user-defined compare function (*ossUserFieldCmp)() is successful, returns zero only if the open type structures have identical user field values. A negative value is returned if data1 is less than data2. A positive value is returned if data1 is greater than data2.
OssGlobal w, *world = &w; Msg myData, myData2; int CDECL_ENTRY_FPTR cpyUF(OssGlobal *world, OpenType *src, OpenType *dest) { /* user-defined OpenType.userField copy function */ strcpy(dest->userField, src->userField); return 0; } int CDECL_ENTRY_FPTR cmpUF(OssGlobal *world, OpenType *data1, OpenType *data2) { /* user-defined OpenType.userField compare function */ return strcmp(data1->userField, data2->userField); } int (CDECL_ENTRY_FPTR *curUserFieldCpy)(OssGlobal *world, OpenType *src, OpenType *dest); int (CDECL_ENTRY_FPTR *curUserFieldCmp)(OssGlobal *world, OpenType *data1, OpenType *data2); . . . myData.tcipType.userField = (char*)malloc(14*sizeof(char)); strcpy(myData.tcipType.userField, "Message Text."); myData2.tcipType.userField = (char*)malloc(14*sizeof(char)); ossSetUserFieldCpyCmp(world, cpyUF, cmpUF); ossGetUserFieldCpyCmp(world, &curUserFieldCpy, &curUserFieldCmp); (curUserFieldCpy)(world, &myData.tcipType, &myData2.tcipType); if(((curUserFieldCmp)(world, &myData.tcipType, &myData2.tcipType)) == 0) ossPrint(world, "Open types have identical user fields.\n"); else ossPrint(world, "Open types do not have identical user fields.\n") . . . free(myData.tcipType.userField); free(myData2.tcipType.userField);
Sets or gets an output stream and a user-defined print function for printing out trace information.
OssBuf encodedData; /* length and address of encoded data */ int (DLL_ENTRY_FPTR *curUserPrint)(OssGlobal *world, const char *format, ...); FILE *curStream; . . . ossSetUserPrint(world, stdout, myPrintFunction); . . . ossGetUserPrint(world, &curStream, &curUserPrint);
To change the default print function, manually assign the asn1prnt function pointer in the OssGlobal structure. For example:
world.asn1prnt = myOwnPrintingFunction;
Sets or gets the default C library vprintf() function and standard output stream with your own custom va_list printing function and standard output stream.
Initializes or releases serialization resources that support cross-thread synchronization. These functions must be called to achieve thread safety in the following situations:
ossInitSync() must be called before the first call to ossinit() | ossWinit().
ossTermSync() must be called after the last call to ossinit() | ossWinit().
If ossInitSync() is successful, returns zero. Otherwise, returns MUTEX_NOT_CREATED.
OssGlobal w, *world = &w; . . . if(!ossInitSync(void)) ossinit(world, bcas); else return;
Converts INTEGER field values of GeneralizedTime or UTCTime types into ASN.1 value string representation.
If successful, it returns zero. Otherwise, it returns BAD_TIME error.
UTCTime myTime; OssGlobal w, *world = &w; char utc_timeString[40], gen_timeString[40]; int retcode; myTime.year=12; myTime.month=8; myTime.day = 23; myTime.hour = 12; myTime.minute = 33; myTime.second=27; myTime.mindiff = -300; ossIntsToUTCTime(world, myTime.year, myTime.month, myTime.day, myTime.hour, myTime.minute, myTime.second, myTime.mindiff, utc_timeString); ossIntsToGeneralizedTime(world, 2001, myTime.month, myTime.day, myTime.hour, myTime.minute, myTime.second, 258, 3, 1, gen_timeString); ossPrint(world, "UTC TimeString: %s \n", utc_timeString); ossPrint(world, "Generalized TimeString: %s \n", gen_timeString);
Prints:
UTC TimeString: 120823123327-0500 Generalized TimeString: 20010823123327.258Z
ossUTCTimeToInts() | ossGeneralizedTimeToInts()
Used with TOED to preallocate a large memory buffer which the encoder/decoder can reuse for temporary storage. This is an alternative that leads to a better performance during encoding/decoding specifications rather than calling several internal malloc() | free() operations to handle temporary storage. Note that you must make sure that the preallocated buffer is freed after encode/decode operations are finished.
If successful, it returns zero. Otherwise, it returns a non-zero value. For non-TOED encoder/decoder, it returns UNIMPLEMENTED.
OssBuf tempBuf; . . . tempBuf.value = (char *)malloc(100000); tempBuf.length = 100000; ossSetTemporaryBuffer(world, &tempBuf);
The temporary memory block must exceed 32 bytes and must be 5 to 10 kilobytes larger than the actual memory needed to hold the encoded/decoded data chunk. To learn how much memory a sample encoded message requires, use ossDetermineEncodingLength(). We recommend that you allocate twice as much memory than is required for the largest PDU. The decoder requires more memory than the encoder needs for the same message.
Allows you to preallocate a memory area for encoding/decoding operations. You can use it if you experience a stack overflow error due to a limited stack space in your operating environment. Make sure you free the preallocated stack-space buffer when you finish using it.
The ossSetUserStack() function is available for SOED. The specific components that benefit from the use of this function are: the PER encoder/decoder, ossCpyValue() function, and ossCmpValue() function.
If successful, it returns zero. Otherwise, it returns a non-zero error. If SOED is not in use or if your runtime platform does not implement dynamic allocation of large chunks of automatic data, it returns UNIMPLEMENTED.
OssGlobal w, *world = &w; OssBuf encodedData; OssBuf stackBuf; int myPduNum = MyASN1DataType_PDU; MyASN1DataType *decodedDataPtr; . . . . stackBuf.value = (*world->mallocp)(4096*sizeof(char));); stackBuf.length = 4096; /* size of initial buffer */ ossSetUserStack(world, &stackBuf); ossDecode(world, &myPduNum, &encodedData, (void **)&decodedDataPtr); . . . . (*world->freep)(stackBuf.value); ossterm(world);
We recommend that you allocate at least twice as much memory than is required for the largest PDU. Through trial and error, a larger chunk of memory is required, depending upon the complexity of your ASN.1 specification.
Constructs the string representation of an ISO 8601 [recurring] time interval in the form of a start-duration pair from its individual components. Use these functions when the TIME type has a Property settings constraint applied, the Basic property is set to [Rec]Interval and Interval-type is set to "SD".
The ossGetTimeKind() function returns the oss_tk_StartPointDuration[Rec]Interval for the newly constructed time value.
If successful, it returns zero. Otherwise, it returns a non-zero error (BAD_TIME).
OssGlobal w, *world = &w; int rc, rec = 0; ossTimePoint start; ossDuration dur; char *result = NULL; . . . ossStringToStartPointDurationRecInterval(world, "R5/1985-04-12T23:20:50/P1Y4M20DT30M", &start, &dur, &rec); dur.years += 2; dur.bit_mask |= OSS_de_hours_present; dur.hours = 1; rec -= 2; ossStartPointDurationRecIntervalToString(world, &start, &dur, rec, &result); ossPrint(world, "Resulting string: %s\n", result); ossFreeBuf(world, result);
Prints:
Resulting string: R3/1985-04-12T23:20:50/P3Y4M20DT1H30M
ossStringToStartPointDurationInterval() | ossStringToStartPointDurationRecInterval()
Constructs the string representation of an ISO 8601 [recurring] time interval in the form of a start-end pair from its individual components. Use these functions when the TIME type has a Property settings constraint applied, the Basic property is set to [Rec]Interval and Interval-type is set to "SE".
The ossGetTimeKind() function returns the oss_tk_StartPointEndPoint[Rec]Intervalfor the newly constructed time value.
If successful, it returns zero. Otherwise, it returns a non-zero error (BAD_TIME).
OssGlobal w, *world = &w; int rc; ossTimePoint start, end; char *result = NULL; . . . ossStringToStartPointEndPointInterval(world, "1985-04-12T23:20:50/1985-06-25T10:30:00", &start, &end); end.seconds = 50; end.years += 4; ossStartPointEndPointIntervalToString(world, &start, &end, &result); ossPrint(world, "Resulting string: %s\n", result); ossFreeBuf(world, result);
Prints
Resulting string: 1985-04-12T23:20:50/1989-06-25T10:30:50
ossStringToStartPointEndPointInterval() | ossStringToStartPointEndPointRecInterval()
Parses the string representation of an ISO 8601 time interval expressed by a [number of recurrences of] "duration-end" pair and creates the parsed (binary) values of the components of this pair [and recurrence]. Use these functions when the ossGetTimeKind() function returns an oss_tk_DurationEndPoint[Rec]Interval for the input time string value. Thus, the corresponding TIME type has a Property settings constraint applied, the Basic property is set to [Rec]Interval, and Interval-type is set to "DE".
If successful, it returns zero. Otherwise, it returns a non-zero error (BAD_TIME).
See ossDurationEndPointIntervalToString()
ossDurationEndPointIntervalToString() | ossDurationEndPointRecIntervalToString()
Parses the string representation of an ISO 8601 [recurring] time interval and creates the parsed (binary) duration value. Use these functions when the ossGetTimeKind() function returns the oss_tk_Duration[Rec]Interval for the input time string value. Thus, the corresponding TIME type has a Property settings constraint applied, the Basic property is set to [Rec]Interval and Interval-type is set to "D".
If successful, it returns zero. Otherwise, it returns a non-zero error (BAD_TIME).
See ossDurationEndPointIntervalToString() | ossDurationIntervalToString().
ossDurationIntervalToString() | ossDurationRecIntervalToString()
Parses the string representation of an ISO 8601 [recurring] time interval expressed by a start-duration pair and creates the parsed (binary) values of the components of this pair. Use these functions when the ossGetTimeKind() function returns theoss_tk_StartPointDuration[Rec]Interval enumeration for the input time string value. Thus, the corresponding TIME type has a Property settings constraint applied, the Basic property is set to [Rec]Interval and Interval-type is set to "SD".
If successful, it returns zero. Otherwise, it returns a non-zero error (BAD_TIME).
See ossStartPointDurationIntervalToString()
ossStartPointDurationIntervalToString() | ossStartPointDurationRecIntervalToString()
Parses the string representation of an ISO 8601 [recurring] time interval expressed by a start-end pair and creates the parsed (binary) values of the components of this pair. Use these functions when the ossGetTimeKind() function returns the oss_tk_StartPointEndPoint[Rec]Intervalenumeration for the input time string value. Thus, the corresponding TIME type has a Property settings constraint applied, the Basic property is set to [Rec]Interval and Interval-type is set to "SE".
If successful, it returns zero. Otherwise, it returns a non-zero error (BAD_TIME).
See ossStartPointEndPointIntervalToString()
ossStartPointEndPointIntervalToString() | ossStartPointEndPointRecIntervalToString()
Converts an ISO 8601 time point value between its string representation and C-representation. Use it when the TIME type has a Property settings constraint applied and the Basic property is set to Time or Date-Time or Date (ossGetTimeKind() returns oss_tk_TimePoint for such time values).
If successful, it returns zero. Otherwise, it returns a non-zero error (BAD_TIME).
OssGlobal w, *world = &w; int rc; ossTimepoint tp; char *result = NULL; /* Let ossTimePointToString allocate memory */ . . . ossStringToTimePoint (world, "1985-05-10", &tp); tp.years = 2006; /* Modify years component */ ossTimePointToString(world, &tp, &result); ossPrint(world, "Resulting string: %s\n", result); ossFreeBuf(world, result);
Prints:
Resulting string: 2006-05-10
ossVprintWin() is similar to the vprintf() C library function. It is called when the Borland C++ Builder (and OSS DLLs) is used with a regular (Microsoft VC++) copy of the OSS ASN.1 Tools for C, in a custom implementation of ossPrint() for such cases. The custom version of ossPrint() is shipped (only in the Windows version) in the samples directory as ossprint.c.
If successful, it returns the number of characters written to the output. Otherwise, it returns -1.
int ossPrint(struct ossGlobal *world, const char *fmt, ...) { int err = 0; va_list ap; va_start(ap, fmt); if (world) err = ossVprintWin(world, fmt, ap); else vrintf(fmt, ap); va_end(ap); return err; }
The functions described in this section are used for converting ASN.1 binary messages to and from XML using one of the ASN.1 XML Encoding Rules: Basic, Canonical, or Extended.
These functions convert ASN.1 binary messages to and from XML using ASN.1 binary encoding rules (BER, CER, DER, PER, CPER, OER, and COER) and XER text encoding rules (Basic XER, Canonical XER and Extended XER). The default XML encoding rules used for conversion are determined by the options specified at ASN.1-compile time (-xer for Basic, -cxer for Canonical, and -exer for Extended XML Encoding Rules). When you specify more than one option, the precedence is: E-XER, XER, CXER.
To set or retrieve the default encoding rules and detailed XER rules, use ossSetXMLEncodingRules() | ossGetXMLEncodingRules().
The ossBinary2XML() and ossXML2Binary() functions perform conversion by decoding and then re-encoding the input message. Starting with version 11.0, the functions check if, at decoding stage, an open type or contents constrained type is left undecoded. This is possible when component relation constraints cannot be resolved for an extensible open type, when the OSS.NoConstrain compiler directive is applied to an open or contents constrained type, or when you use the TOED library without specifying the -autoencdec and -constraints options at ASN.1 compile time. Such an undecoded type cannot be converted. In this case, the functions issue the D0373S error and return the CONVERSION_NOT_POSSIBLE code.
If successful, it returns zero. Otherwise, it returns a non-zero value.
ossGetXMLEncodingRules() | ossSetXMLEncodingRules()
These functions convert XML Schema date and/or time types, including duration, gYear, gMonthDay, etc., to and from string representation and C INTEGERs (representing individual components of date or time).
If successful, it returns zero. Otherwise, it returns a non-zero value (BAD_TIME).
OssGlobal w; int year, month, day, hours, minutes, seconds, precision, local_utc_mindiff; char *fractions = 0; . . . ossDateToInts (&w, "1985-05-10+05:00", &year, &month, &day, &local_utc_mindiff); ossPrint(&w, "Year: %d, Month: %d, Day: %d, UTC min diff: %d.\n", year, month, day, local_utc_mindiff); . . . char * dateString = NULL; ossIntsToDate (world, 2003, 11, 15, -120, &dateString); ossPrint(world, "Date string: %s.\n", dateString); ossFreeBuf(world, dateString); . . . ossDateTimeToInts (world, "2003-11-15T13:22:05.234-01:30", &year, &month, &day, &hours, &minutes, &seconds, &fraction, &precision, &local_utc_mindiff); ossPrint(world, "Year: %d, Month: %d, Day: %d, Hours: %d, Minutes: %d \n", year, month, day, hours, minutes); ossPrint(world, "Seconds: %d, Fractions: %.*s, UTC min dif: %d. \n", seconds, precision, fractions, local_utc_mindiff); . . . ossBoolean negative; ossDurationToInts (world, "P5Y2M5D10H30M25.65S", &negative, &years, &months, &days, &hours, &minutes, &seconds, &fraction, &precision); ossPrint(world, "Y: %d, M: %d, D: %d, H: %d, M: %d, "S: %d, F: %.*s. \n", year, month, day, hours, minutes, seconds, precision, fractions); . . . ossGMonthDayToInts (world, "--06-22Z", &month, &day, &local_utc_mindiff); ossPrint(world, "Month: %d, Day: %d", month, day); if(local_utc_mindiff == OSS_UTC_DIFF_Z){ ossPrint(world, " Coordinated Universal Time.\n"); } else if(local_utc_mindiff == OSS_UTC_DIFF_ABSENT){ ossPrint(world, " no Time Zone specified.\n"); } else { ossPrint(world, ", UTC minutes: %d.\n", local_utc_mindiff); }
Prints:
Year: 1985, Month: 5, Day: 10, UTC min diff: 300. Date string: 2003-11-15-02:00. Year: 2003, Month: 11, Day: 15, Hours: 13, Minutes: 22 Seconds: 5, Fraction: 234, UTC min dif: -90. YY: 5, M: 2, D: 5, H: 10, M: 30 S: 25, F: 65. Month: 6, Day: 22 Coordinated Universal Time.
The Coordinated Universal Time (UTC) difference is represented in number of minutes. Two special values, OSS_UTC_DIFF_Z and OSS_UTC_DIFF_ABSENT (defined to UINT_MAX and UINT_MAX - 1, respectively) indicate that the zone is UTC (with "Z" and no difference) or indicate that no time zone is specified, respectively. Any other values of local_utc_mindiff, positive or negative, are interpreted as time zone specifications. The absolute value for local_utc_mindiff cannot exceed 840 minutes (14 hours).
The parts in the duration input string are optional, and you can have at least one. The function ossDurationToInts() outputs zero for the fields that are absent in the input durationString.
Gets or sets a prefix string to associate with a namespace declared (using E-XER encoding instructions) in one of the input ASN.1 specifications. The prefix affects only the encoder and sets the default namespace as the namespace of the root element of the E-XER encoding. For other namespaces used in the E-XER encoding, the encoder uses prefixes declared in the ASN.1 specification.
The encoder assigns prefixes to namespace URIs under the following circumstances:
If successful, it returns zero. Otherwise, it returns a non-zero value.
/* set the prefix "ex" to the namespace "http://example.org" */ prefixChanged = ossSetNamespacePrefix (world, "http://example.org", "ex"); if(prefixChanged == 0) ossPrint("Prefix 'ex' set for the namespace 'http://example.org"."));
If your original schema contains unqualified elements, wildcards, or uses QNames (as defined by the W3C XML Namespaces document), you cannot set the default namespace (you cannot specify a NULL prefix). Otherwise, the function returns DEFAULT_PREFIX_NOT_ALLOWED.
For namespaces used in an E-XER encoding that are not declared in the input schemas (such as the URI component of a QName value), the encoder generates artificially non-empty prefixes that are guaranteed to be unique in the E-XER encoding.
Gets or sets the XML encoding rules used by ossXML2Binary() and ossBinary2XML() for performing direct conversions from XML to binary and vice versa. The XML encoding rules returned are: Basic XML Encoding Rules (OSS_XER), Canonical Encoding Rules (OSS_CXER), or Extended Encoding Rules (OSS_EXER). The default XML encoding rules used for conversion are determined by the options specified at ASN.1-compile time (-xer for Basic, -cxer for Canonical and -exer for Extended XML Encoding Rules, accordingly). When you specify more than one option, the precedence is: E-XER, XER, CXER.
ossGetXMLEncodingRules() function returns one of the XML encoding rules: OSS_EXER, OSS_XER, OSS_CXER. If none of them is accessible, the function returns -1.
If successful, ossSetXMLEncodingRules() returns a value of zero. Otherwise, it returns a non-zero value (BAD_ENCRULES).
ossBinary2XML() | ossXML2Binary()
Finds the compiler-generated PDU identifier associated with an XML element name. The name is interpreted as the root E-XER element name. The matching PDU (if any) is identified and its number is returned by the function. If there are several PDU types with the same root element name in the input syntax, the function returns DATA_ERROR.
If successful, it returns zero. Otherwise, it returns an error code.
Prints well-formatted XER encodings. We recommend that you use this function when printing an XER encoding.
OssGlobal w, *world = &w; MyASN1PDU *inputData; OssBuf encodedData; . . . ossEncode(world, myPduNum, inputData, &encodedData); ossPrintXML(world, encodedData.value, encodedData.length, TRUE);
Specifies the general data schema (DTD - Data Type Definition) that corresponds to an XER encoding. You can use it to view and edit the output produced by ossEncode() in a non-ASN.1-specific XML tool. pduName and externalID must be global strings that remain accessible for all subsequent calls of ossEncode()(the library does not save a copy of these strings).
If successful, it returns zero. Otherwise, it returns a non-zero value.
ossSetXmlDTD(world, "Record", "dtd/Record.dtd", OSS_XDTD_SYSTEM);
The following line is added in the subsequent XER encodings:
<!DOCTYPE Record SYSTEM "dtd/Record.dtd">
Provides control over the browser format of the XML output produced by the ossEncode() function. It instructs the encoder to include a reference to an XSL stylesheet in the XER encoding. xslFilePath must point to a global string that remains accessible for all subsequent calls of the ossEncode()(the library does not save a copy of this string).
If successful, it returns zero. Otherwise, it returns a non-zero value.
ssSetXmlStylesheet(world, "xsl/customized-Record.xsl");
The encoder places the following line in the output XER encoding:
<?xml:stylesheet type="text/xsl" href="xsl/customized-Record.xsl"?>
This section describes functions used to compress ASN.1 encodings employing either an algorithm implemented by the standard zlib or a custom compression algorithm. For more details and examples, see Zlib Compression.
Compress or uncompress the encoding data via built-in zlib compressor. These functions cannot be used if you specify an alternative data transformation routine with the ossSetCompressDecompressFunctions() function.
If successful, it returns zero. Otherwise, it returns a non-zero value.
OssGlobal *world; OssBuf encodedData; /* length and address of encoded data */ /* length and address of encoded compressed data */ OssBuf compressedData; /* length and address of encoded decompressed data */ OssBuf decompressedData; DataPacket myPacket; /* unencoded data */ DataPacket *decodedPacketPtr; /* address of decoded data */ int pdu_num = DataPacket_PDU; . . . . encodedData.value = NULL; /* Intialize encoder output buffer */ encodedData.length = 0; /* Encode the data. Return non-zero for failure. */ if (ossEncode(world, DataPacket_PDU, &myPacket, &encodedData)) { ossPrint(world, "%s\n", ossGetErrMsg(world)); /* an error occurred, * print errmsg */ ossterm(world); /* Free up allocated resources */ return 1; } compressedData.value = NULL; /* Intialize output buffer */ compressedData.length = 0; /* Compress the data. Return non-zero for failure. */ if (ossCompress(world, &encodedData, &compressedData, 0)) { ossPrint(world, "%s\n", ossGetErrMsg(world)); /* an error occurred, * print errmsg */ ossFreeBuf(world, encodedData.value); /* Free up encoder output buffer */ ossterm(world); /* Free up allocated resources */ return 1; } ossFreeBuf(world, encodedData.value); /* Free up encoder output buffer */ decompressedData.value = NULL; /* Intialize output buffer */ decompressedData.length = 0; /* Decompress the data. Return non-zero for failure. */ if (ossUnCompress(world, &compressedData, &decompressedData, FALSE)) { ossPrint(world, "%s\n", ossGetErrMsg(world)); /* an error occurred, * print errmsg */ /* Free up compression output buffer */ ossFreeBuf(world, compressedData.value); ossterm(world); /* Free up allocated resources */ return 1; } ossFreeBuf(world, compressedData.value); /* Free up compression output buffer */ decodedPacketPtr = NULL; /* Decode the data. Return non-zero for failure. */ if (ossDecode(world, &pdu_num, &decompressedData, (void **)&decodedPacketPtr)) { ossPrint(world, "%s\n", ossGetErrMsg(world)); /* an error occurred, * print errmsg */ /* Free up decompression output buffer */ ossFreeBuf(world, decompressedData.value); ossterm(world); /* Free up allocated resources */ return 1; } else { /* Print out the data that was just decoded. */ /* Free up decompression output buffer */ ossFreeBuf(world, decompressedData.value); ossPrint(world, "\nData decoded to:\n\n"); /* successfully decoded */ ossPrintPDU(world, pdu_num, decodedPacketPtr); ossFreePDU(world, pdu_num, decodedPacketPtr); /* free up PDU */ ossterm(world); /* Free up allocated resources */ return 0; }
This feature is supported only for the default memory manager.
Sets or gets the user-defined compression and decompression (and/or encryption) functions to be used by the encoder or decoder after the USE_COMPRESSION flag was set. By default, the built-in zlib-based compression or decompression routines are used. If you set the function pointer to NULL, compression or decompression is disabled.
typedef int (DLL_ENTRY_FPTR *_System ossCompFcnPtr)(OssGlobal *world, unsigned char *outbuf, unsigned long *outlen, unsigned char *inbuf, unsigned long inlen, void *info);inbuf/outbuf and inlen/outlen represent the input/output encoding and length (in bytes) (outlen on entry holds the size in bytes of the encoder/decoder library-allocated output buffer; on exit, set to the size in bytes of the data actually written to the output buffer).
If successful, it returns zero. Otherwise, it returns a non-zero value.
Sets or gets auxiliary information for the current set of compression and decompression (and/or encryption) functions. For the default zlib you can set the compression level.
If successful, it returns zero. Otherwise, it returns a non-zero value.
int compression_level = 9; /* Z_BEST_COMPRESSION */ . . . ossSetCompressDecompressInfo(world, (void *)&compression_level);
After the call, you can change the value of the compression_level variable without calling the API function, since the passed address references the variable and automatically customizes the compression settings.
Sets or gets the compression size estimating function when using custom compression or encryption routines.
This function estimates the maximum size of compressed data for a given uncompressed PDU. It is useful when allocating memory buffer for the compressed encoding.
By default, the zlib estimation formula is used: the maximum size of the compressed encoding will not exceed the size of the uncompressed data + 0.1% of the uncompressed data size + 12 bytes, regardless of the encoding. However, when using your custom compression/encryption function, this formula might not be applicable and you must provide another maximum size estimating function.
typedef unsigned long (DLL_ENTRY_FPTR *_System ossCompEstFcnPtr) (unsigned char *inbuf, unsigned long inlen, void *info)inbuf/inlen is the input uncompressed encoding buffer and length in bytes.
If successful, it returns zero. Otherwise, it returns a non-zero value.
unsigned long DLL_ENTRY_FDEF zlibEstimator( unsigned char *inbuf, unsigned long inlen, void *info) { return (unsigned long)(inlen * 1.001 + 12); } . . . ossSetCompSizeEstimator(world, zlibEstimator);
Returns the length of the original (uncompressed) and the compressed encoding and modifies the input structure so that the prefix is ignored (an encoding consists of a compression prefix followed by the compressed encoding).
If successful, it returns zero. Otherwise, it returns a non-zero value.
This documentation applies to the OSS® ASN.1 Tools for C release 11.3 and later.
Copyright © 2024 OSS Nokalva, Inc. All rights reserved.
No part of this publication may be reproduced, stored in a retrieval system, or transmitted in any form or by any means electronic, mechanical, photocopying, recording or otherwise, without the prior permission of OSS Nokalva, Inc.
Every distributed copy of the OSS® ASN.1 Tools for C is associated with a specific license and related unique license number. That license determines, among other things, what functions of the OSS ASN.1 Tools for C are available to you.