TOP

Zlib Compression

Applies to: ASN.1/C 10.5

Using Compression with SOED and LED

SOED and LED support compression and decompression for ASN.1 encodings, which can come in handy when using verbose text encodings such as XER and E-XER. The compression algorithm is implemented by the standard zlib. Additionally, you can use a custom compression or decompression zlib, or any kind of data transformation.

To use compression or decompression, compile your input ASN.1 specification with the -compress option and set the USE_COMPRESSION runtime flag (see ossSetFlags()).

A compressed encoding contains two parts:

  • The compression prefix
  • The compressed encoded data

The compression prefix includes the length of the original (uncompressed) encoding and the length of the compressed encoding. Each length value is encoded as a sequence of octets, where the most significant bit of each octet is set to '0' or '1', indicating whether it's the last one or not. The other seven bits of each octet represent a binary-encoded integer number.

The following functions are useful when compressing or decompressing ASN.1 encodings:

  • ossSetCompressDecompressFunctions(), to use a different compression routine or an encryption/transformation routine.
  • ossSetCompressDecompressInfo(), to pass more information to your custom compression and decompression functions.
  • ossSetCompSizeEstimator(), to change the estimating function which predicts the maximum compressed data size
  • ossCompress() and ossUnCompress(), to call standalone functions, in which case you do not need to set the USE_COMPRESSION runtime flag. You can use both automatic and standalone compression. For example, an encoding compressed by ossCompress() can be decoded by the ossDecode() using the "built-in" decompression, and vice versa.

NOTE: The file or the socket memory managers do not support the compression feature.

NOTE: Starting with version 8.6, a separate zlib library is not provided in the OSS ASN.1 Tools shipment.

Examples

The following examples show you how to use compression API.

Default (zlib) compression

The uncompressed BER encoding size for the following PDU is 52 bytes.

ASN.1 file:

M DEFINITIONS ::= BEGIN
S ::= IA5String
-- the value is chosen to be a compressible one
s S ::= "Hello world! Hello world! Hello world! Hello world"
END

ASN.1 compiler command line:

asn1 sample -ber -compress

C code (zlib_sample.c, error check removed for brevity):

#include "sample.h"
int main() {
int err, pdu_num = 0;
OssGlobal world;
OssBuf encodedData;
void *data = NULL;
ossinit(&world, sample);
world.asn1chop = 0; /* do not truncate long printed lines */
ossSetFlags(&world, ossGetFlags(&world) | USE_COMPRESSION);
encodedData.value = NULL;
encodedData.length = 0;
ossEncode(&world, S_PDU, &s, &encodedData);
  ossPrint(&world, "PDU encoded in %ld bytes:\n", encodedData.length);
ossPrintHex(&world, (char *)encodedData.value, encodedData.length);
ossDecode(&world, &pdu_num, &encodedData, &data);
ossPrint(&world, "\nDecoded successfully.\n\n");
ossPrintPDU(&world, pdu_num, data);
ossFreeBuf(&world, encodedData.value);
ossFreePDU(&world, pdu_num, data);
ossterm(&world);
return 0;
}

C compiler command line ($OSS_ROOT is a directory where the OSS ASN.1 Tools package is installed, $ZLIB_ROOT is a directory where zlib is installed):

gcc -o zlib_sample -I$(OSS_ROOT)/include zlib_sample.c 
sample.c $(OSS_ROOT)/libasn1code.a $(ZLIB_ROOT)/libz.a

Sample output:

PDU encoded in 27 bytes:
3419789C 1333F248 CDC9C957 28CF2FCA 49515420 8A0300CE E711FC
Decoded successfully.
value S ::= "Hello world! Hello world! Hello world! Hello world"

Customized Compression/Decompression - Encryption

The encryption algorithm has a single parameter - a byte that is XOR'ed with all bytes from the input buffer and added to the end of the buffer. The application sets a pair of custom "codecs", a "compression information" (the byte parameter) and a custom "size estimator" functions.

ASN.1 file (sample.asn):

M DEFINITIONS ::= BEGIN
S ::= IA5String
s S ::= "Hello world!"
END

ASN.1 compiler command line (-compress is not specified, because zlib is not used):

asn1 sample -ber

C application file (custom_sample.c, error check is removed for brevity):

#include "sample.h"
unsigned char xor_byte = 0xAA;
int DLL_ENTRY_FDEF usrEncrypt(struct ossGlobal *world,
unsigned char *outbuf, unsigned long *outlen,
unsigned char *inbuf, unsigned long inlen, void *info)
{
int i;
if (*outlen < inlen + 1) 
return -1;
for (i = 0; i < inlen; i++)
outbuf[i] = inbuf[i] ^ *((unsigned char *)info);
outbuf[inlen] = *((unsigned char *)info);
*outlen = inlen + 1;
return 0;
}
int DLL_ENTRY_FDEF usrDecrypt(struct ossGlobal *world,
unsigned char *outbuf, unsigned long *outlen,
unsigned char *inbuf, unsigned long inlen, void *info)
{
int i;
if (*outlen < inlen - 1)
return -1;
for (i = 0; i < inlen - 1; i++)
outbuf[i] = inbuf[i] ^ inbuf[inlen - 1];
*outlen = inlen - 1;
return 0;
}
unsigned long DLL_ENTRY_FDEF usrEstimate(unsigned char *inbuf,
unsigned long inlen, void *info)
{
return inlen + 1;
}
int main() {
int err, pdu_num = 0;
OssGlobal world;
OssBuf encodedData;
void *data = NULL;
ossinit(&world, sample);
world.asn1chop = 0; /* do not truncate long printed lines */
ossSetFlags(&world, USE_COMPRESSION);
ossSetCompressDecompressFunctions(&world,
(ossCompFcnPtr)&usrEncrypt,
(ossCompFcnPtr)&usrDecrypt);
ossSetCompressDecompressInfo(&world, (void *)&xor_byte);
ossSetCompSizeEstimator(&world, (ossCompEstFcnPtr)&usrEstimate);
encodedData.value = NULL;
encodedData.length = 0;
ossEncode(&world, S_PDU, &s, &encodedData);
 ossPrint(&world, "PDU encoded in %ld bytes:\n", encodedData.length);
ossPrintHex(&world, (char *)encodedData.value, encodedData.length);
ossDecode(&world, &pdu_num, &encodedData, &data); ossPrint(&world, "\nDecoded successfully.\n\n");
ossPrintPDU(&world, pdu_num, data);
ossFreeBuf(&world, encodedData.value);
ossFreePDU(&world, pdu_num, data);
ossterm(&world);
return 0;
}

The C compiler command line ($OSS_ROOT is a directory where the OSS ASN.1 Tools package is installed). The zlib library is not used:

gcc -o custom_sample -I$OSS_ROOT/include custom_sample.c sample.c $OSS_ROOT/libasn1code.a

Sample output:

PDU encoded in 17 bytes:
0E0FBCA6 E2CFC6C6 C58ADDC5 D8C6CE8B AA
Decoded successfully.
value S ::= "Hello world!"

Standalone ossCompress/ossUnCompress Functions

When using the standalone compression API:

  • There is no need to set the USE_COMPRESS the runtime flag.
  • There is no limitation in applying the ASN1.DeferDecoding and OSS.NOCOPY directives.

ASN.1 file (sample.asn):

M DEFINITIONS ::= BEGIN
S ::= IA5String
-- the value is chosen to be a packable one
s S ::= "Hello world! Hello world! Hello world! Hello world"
END

ASN.1 compiler command line:

asn1 sample -ber -compress

C app file (zlib_sample2.c, error check removed for brevity):

#include "sample.h"
int main() {
int err, pdu_num = 0;
OssGlobal world;
OssBuf encodedData, tmpData;
void *data = NULL; 
ossinit(&world, sample);
world.asn1chop = 0; /* do not truncate long printed lines */
ossPrint(&world, "Unencoded PDU:\n");
ossPrintPDU(&world, S_PDU, &s); 
encodedData.value = NULL;
encodedData.length = 0;
			
ossEncode(&world, S_PDU, &s, &encodedData);
ossPrint(&world, "PDU encoded in %ld bytes:\n", encodedData.length);
ossPrintHex(&world, (char *)encodedData.value, encodedData.length);
tmpData.value = NULL;
tmpData.length = 0;
ossCompress(&world, &encodedData, &tmpData, 0);
ossFreeBuf(&world, encodedData.value);
encodedData = tmpData;
ossPrint(&world, "Encoding compressed in %ld 
bytes:\n", encodedData.length);
ossPrintHex(&world, (char *)encodedData.value, encodedData.length);
tmpData.value = NULL;
tmpData.length = 0;
ossUnCompress(&world, &encodedData, &tmpData, FALSE);
ossFreeBuf(&world, encodedData.value);
encodedData = tmpData;
ossPrint(&world, "Encoding decompressed in %ld bytes:\n", encodedData.length);
ossPrintHex(&world, (char *)encodedData.value, encodedData.length);
ossDecode(&world, &pdu_num, &encodedData, &data);
ossPrint(&world, "Decoded successfully.\n");
ossPrintPDU(&world, pdu_num, data);
ossFreeBuf(&world, encodedData.value);
ossFreePDU(&world, pdu_num, data);
ossterm(&world);
return 0;
}

C compiler command line ($OSS_ROOT is a directory where the OSS ASN.1 Tools package is installed, $ZLIB_ROOT is a directory where zlib is installed):

gcc -o zlib_sample2 -I$OSS_ROOT/include zlib_sample2.c 
sample.c $OSS_ROOT/libasn1code.a $ZLIB_ROOT/libz.a

Sample output:

Unencoded PDU:
value S ::= "Hello world! Hello world! Hello wor ..."
PDU encoded in 52 bytes:
16324865 6C6C6F20 776F726C 64212048 656C6C6F 20776F72 6C642120 48656C6C
6F20776F 726C6421 2048656C 6C6F2077 6F726C64
Encoding compressed in 27 bytes:
3419789C 1333F248 CDC9C957 28CF2FCA 49515420 8A0300CE E711FC
Encoding decompressed in 52 bytes:
16324865 6C6C6F20 776F726C 64212048 656C6C6F 20776F72 6C642120 48656C6C
6F20776F 726C6421 2048656C 6C6F2077 6F726C64
Decoded successfully.
value S ::= "Hello world! Hello world! Hello wor ..."

This documentation applies to the OSS® ASN.1 Tools for C release 10.5 and later.

Copyright © 2017 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.