Commit 523de9eb authored by Lev Walkin's avatar Lev Walkin

per support

parent 1dc85299
......@@ -21,7 +21,7 @@ asn_TYPE_descriptor_t asn_DEF_ANY = {
OCTET_STRING_encode_der,
OCTET_STRING_decode_xer_hex,
ANY_encode_xer,
0,
0, 0,
0, /* Use generic outmost tag fetcher */
0, 0, 0, 0,
0, /* No PER visible constraints */
......
......@@ -28,6 +28,7 @@ asn_TYPE_descriptor_t asn_DEF_BIT_STRING = {
OCTET_STRING_decode_xer_binary,
BIT_STRING_encode_xer,
OCTET_STRING_decode_uper, /* Unaligned PER decoder */
OCTET_STRING_encode_uper, /* Unaligned PER encoder */
0, /* Use generic outmost tag fetcher */
asn_DEF_BIT_STRING_tags,
sizeof(asn_DEF_BIT_STRING_tags)
......
......@@ -23,7 +23,7 @@ asn_TYPE_descriptor_t asn_DEF_BMPString = {
OCTET_STRING_encode_der,
BMPString_decode_xer, /* Convert from UTF-8 */
BMPString_encode_xer, /* Convert to UTF-8 */
0,
0, 0,
0, /* Use generic outmost tag fetcher */
asn_DEF_BMPString_tags,
sizeof(asn_DEF_BMPString_tags)
......
......@@ -23,6 +23,7 @@ asn_TYPE_descriptor_t asn_DEF_BOOLEAN = {
BOOLEAN_decode_xer,
BOOLEAN_encode_xer,
BOOLEAN_decode_uper, /* Unaligned PER decoder */
BOOLEAN_encode_uper, /* Unaligned PER encoder */
0, /* Use generic outmost tag fetcher */
asn_DEF_BOOLEAN_tags,
sizeof(asn_DEF_BOOLEAN_tags) / sizeof(asn_DEF_BOOLEAN_tags[0]),
......@@ -266,3 +267,18 @@ BOOLEAN_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
return rv;
}
asn_enc_rval_t
BOOLEAN_encode_uper(asn_TYPE_descriptor_t *td,
asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) {
const BOOLEAN_t *st = (const BOOLEAN_t *)sptr;
asn_enc_rval_t er;
(void)constraints;
if(!st) _ASN_ENCODE_FAILED;
per_put_few_bits(po, *st ? 1 : 0, 1);
_ASN_ENCODED_OK(er);
}
......@@ -27,6 +27,7 @@ der_type_encoder_f BOOLEAN_encode_der;
xer_type_decoder_f BOOLEAN_decode_xer;
xer_type_encoder_f BOOLEAN_encode_xer;
per_type_decoder_f BOOLEAN_decode_uper;
per_type_encoder_f BOOLEAN_encode_uper;
#ifdef __cplusplus
}
......
/*-
* Copyright (c) 2003, 2005 Lev Walkin <vlm@lionet.info>. All rights reserved.
* Copyright (c) 2003, 2005, 2006 Lev Walkin <vlm@lionet.info>.
* All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
#include <asn_internal.h>
......@@ -24,6 +25,7 @@ asn_TYPE_descriptor_t asn_DEF_ENUMERATED = {
INTEGER_decode_xer, /* This is temporary! */
INTEGER_encode_xer,
ENUMERATED_decode_uper, /* Unaligned PER decoder */
ENUMERATED_encode_uper, /* Unaligned PER encoder */
0, /* Use generic outmost tag fetcher */
asn_DEF_ENUMERATED_tags,
sizeof(asn_DEF_ENUMERATED_tags) / sizeof(asn_DEF_ENUMERATED_tags[0]),
......@@ -54,3 +56,16 @@ ENUMERATED_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td
rval.code = RC_FAIL;
return rval;
}
asn_enc_rval_t
ENUMERATED_encode_uper(asn_TYPE_descriptor_t *td,
asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) {
ENUMERATED_t *st = (ENUMERATED_t *)sptr;
long value;
if(asn_INTEGER2long(st, &value))
_ASN_ENCODE_FAILED;
return NativeEnumerated_encode_uper(td, constraints, &value, po);
}
......@@ -16,6 +16,7 @@ typedef INTEGER_t ENUMERATED_t; /* Implemented via INTEGER */
extern asn_TYPE_descriptor_t asn_DEF_ENUMERATED;
per_type_decoder_f ENUMERATED_decode_uper;
per_type_encoder_f ENUMERATED_encode_uper;
#ifdef __cplusplus
}
......
......@@ -22,7 +22,7 @@ asn_TYPE_descriptor_t asn_DEF_GeneralString = {
OCTET_STRING_encode_der,
OCTET_STRING_decode_xer_hex,
OCTET_STRING_encode_xer,
0,
0, 0,
0, /* Use generic outmost tag fetcher */
asn_DEF_GeneralString_tags,
sizeof(asn_DEF_GeneralString_tags)
......
......@@ -152,7 +152,7 @@ asn_TYPE_descriptor_t asn_DEF_GeneralizedTime = {
GeneralizedTime_encode_der,
OCTET_STRING_decode_xer_utf8,
GeneralizedTime_encode_xer,
0,
0, 0,
0, /* Use generic outmost tag fetcher */
asn_DEF_GeneralizedTime_tags,
sizeof(asn_DEF_GeneralizedTime_tags)
......
......@@ -22,7 +22,7 @@ asn_TYPE_descriptor_t asn_DEF_GraphicString = {
OCTET_STRING_encode_der,
OCTET_STRING_decode_xer_hex,
OCTET_STRING_encode_xer, /* Can't expect it to be ASCII/UTF8 */
0,
0, 0,
0, /* Use generic outmost tag fetcher */
asn_DEF_GraphicString_tags,
sizeof(asn_DEF_GraphicString_tags)
......
......@@ -22,7 +22,7 @@ asn_TYPE_descriptor_t asn_DEF_IA5String = {
OCTET_STRING_encode_der,
OCTET_STRING_decode_xer_utf8,
OCTET_STRING_encode_xer_utf8,
0,
0, 0,
0, /* Use generic outmost tag fetcher */
asn_DEF_IA5String_tags,
sizeof(asn_DEF_IA5String_tags)
......
/*-
* Copyright (c) 2003, 2004, 2005 Lev Walkin <vlm@lionet.info>.
* Copyright (c) 2003, 2004, 2005, 2006 Lev Walkin <vlm@lionet.info>.
* All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
......@@ -25,6 +25,7 @@ asn_TYPE_descriptor_t asn_DEF_INTEGER = {
INTEGER_decode_xer,
INTEGER_encode_xer,
INTEGER_decode_uper, /* Unaligned PER decoder */
INTEGER_encode_uper, /* Unaligned PER encoder */
0, /* Use generic outmost tag fetcher */
asn_DEF_INTEGER_tags,
sizeof(asn_DEF_INTEGER_tags) / sizeof(asn_DEF_INTEGER_tags[0]),
......@@ -530,6 +531,78 @@ INTEGER_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
return rval;
}
asn_enc_rval_t
INTEGER_encode_uper(asn_TYPE_descriptor_t *td,
asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) {
asn_enc_rval_t er;
INTEGER_t *st = (INTEGER_t *)sptr;
const uint8_t *buf;
const uint8_t *end;
asn_per_constraint_t *ct;
long value = 0;
if(!st || st->size == 0) _ASN_ENCODE_FAILED;
if(!constraints) constraints = td->per_constraints;
ct = constraints ? &constraints->value : 0;
er.encoded = 0;
if(ct) {
int inext = 0;
if(asn_INTEGER2long(st, &value))
_ASN_ENCODE_FAILED;
/* Check proper range */
if(ct->flags & APC_SEMI_CONSTRAINED) {
if(value < ct->lower_bound)
inext = 1;
} else if(ct->range_bits >= 0) {
if(value < ct->lower_bound
|| value > ct->upper_bound)
inext = 1;
}
ASN_DEBUG("Value %ld (%02x/%d) lb %ld ub %ld %s",
value, st->buf[0], st->size,
ct->lower_bound, ct->upper_bound,
inext ? "ext" : "fix");
if(ct->flags & APC_EXTENSIBLE) {
if(per_put_few_bits(po, inext, 1))
_ASN_ENCODE_FAILED;
if(inext) ct = 0;
} else if(inext) {
_ASN_ENCODE_FAILED;
}
}
/* X.691, #12.2.2 */
if(ct && ct->range_bits >= 0) {
/* #10.5.6 */
ASN_DEBUG("Encoding integer with range %d bits",
ct->range_bits);
if(per_put_few_bits(po, value - ct->lower_bound,
ct->range_bits))
_ASN_ENCODE_FAILED;
_ASN_ENCODED_OK(er);
}
if(ct && ct->lower_bound) {
ASN_DEBUG("Adjust lower bound to %ld", ct->lower_bound);
/* TODO: adjust lower bound */
_ASN_ENCODE_FAILED;
}
for(buf = st->buf, end = st->buf + st->size; buf < end;) {
ssize_t mayEncode = uper_put_length(po, end - buf);
if(mayEncode < 0)
_ASN_ENCODE_FAILED;
if(per_put_many_bits(po, buf, 8 * mayEncode))
_ASN_ENCODE_FAILED;
}
_ASN_ENCODED_OK(er);
}
int
asn_INTEGER2long(const INTEGER_t *iptr, long *lptr) {
uint8_t *b, *end;
......
......@@ -38,6 +38,7 @@ der_type_encoder_f INTEGER_encode_der;
xer_type_decoder_f INTEGER_decode_xer;
xer_type_encoder_f INTEGER_encode_xer;
per_type_decoder_f INTEGER_decode_uper;
per_type_encoder_f INTEGER_encode_uper;
/***********************************
* Some handy conversion routines. *
......
......@@ -22,7 +22,7 @@ asn_TYPE_descriptor_t asn_DEF_ISO646String = {
OCTET_STRING_encode_der,
OCTET_STRING_decode_xer_utf8,
OCTET_STRING_encode_xer_utf8,
0,
0, 0,
0, /* Use generic outmost tag fetcher */
asn_DEF_ISO646String_tags,
sizeof(asn_DEF_ISO646String_tags)
......
......@@ -24,6 +24,7 @@ asn_TYPE_descriptor_t asn_DEF_NULL = {
NULL_decode_xer,
NULL_encode_xer,
NULL_decode_uper, /* Unaligned PER decoder */
NULL_encode_uper, /* Unaligned PER encoder */
0, /* Use generic outmost tag fetcher */
asn_DEF_NULL_tags,
sizeof(asn_DEF_NULL_tags) / sizeof(asn_DEF_NULL_tags[0]),
......@@ -130,3 +131,17 @@ NULL_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
rv.consumed = 0;
return rv;
}
asn_enc_rval_t
NULL_encode_uper(asn_TYPE_descriptor_t *td, asn_per_constraints_t *constraints,
void *sptr, asn_per_outp_t *po) {
asn_enc_rval_t er;
(void)td;
(void)constraints;
(void)sptr;
(void)po;
er.encoded = 0;
_ASN_ENCODED_OK(er);
}
......@@ -24,6 +24,7 @@ der_type_encoder_f NULL_encode_der;
xer_type_decoder_f NULL_decode_xer;
xer_type_encoder_f NULL_encode_xer;
per_type_decoder_f NULL_decode_uper;
per_type_encoder_f NULL_encode_uper;
#ifdef __cplusplus
}
......
......@@ -29,6 +29,7 @@ asn_TYPE_descriptor_t asn_DEF_NativeEnumerated = {
NativeInteger_decode_xer,
NativeEnumerated_encode_xer,
NativeEnumerated_decode_uper,
NativeEnumerated_encode_uper,
0, /* Use generic outmost tag fetcher */
asn_DEF_NativeEnumerated_tags,
sizeof(asn_DEF_NativeEnumerated_tags) / sizeof(asn_DEF_NativeEnumerated_tags[0]),
......@@ -70,8 +71,9 @@ NativeEnumerated_encode_xer(asn_TYPE_descriptor_t *td, void *sptr,
}
asn_dec_rval_t
NativeEnumerated_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) {
NativeEnumerated_decode_uper(asn_codec_ctx_t *opt_codec_ctx,
asn_TYPE_descriptor_t *td, asn_per_constraints_t *constraints,
void **sptr, asn_per_data_t *pd) {
asn_INTEGER_specifics_t *specs = (asn_INTEGER_specifics_t *)td->specifics;
asn_dec_rval_t rval = { RC_OK, 0 };
long *native = (long *)*sptr;
......@@ -123,3 +125,80 @@ NativeEnumerated_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor
return rval;
}
static int
NativeEnumerated__compar_value2enum(const void *ap, const void *bp) {
const asn_INTEGER_enum_map_t *a = ap;
const asn_INTEGER_enum_map_t *b = bp;
if(a->nat_value == b->nat_value)
return 0;
if(a->nat_value < b->nat_value)
return -1;
return 1;
}
asn_enc_rval_t
NativeEnumerated_encode_uper(asn_TYPE_descriptor_t *td,
asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) {
asn_INTEGER_specifics_t *specs = (asn_INTEGER_specifics_t *)td->specifics;
asn_enc_rval_t er;
long native, value;
asn_per_constraint_t *ct;
int inext = 0;
asn_INTEGER_enum_map_t key;
asn_INTEGER_enum_map_t *kf;
if(!sptr) _ASN_ENCODE_FAILED;
if(!specs) _ASN_ENCODE_FAILED;
if(constraints) ct = &constraints->value;
else if(td->per_constraints) ct = &td->per_constraints->value;
else _ASN_ENCODE_FAILED; /* Mandatory! */
ASN_DEBUG("Encoding %s as NativeEnumerated", td->name);
er.encoded = 0;
native = *(long *)sptr;
if(native < 0) _ASN_ENCODE_FAILED;
key.nat_value = native;
kf = bsearch(&key, specs->value2enum, specs->map_count,
sizeof(key), NativeEnumerated__compar_value2enum);
if(!kf) {
ASN_DEBUG("No element corresponds to %ld", native);
_ASN_ENCODE_FAILED;
}
value = kf - specs->value2enum;
if(ct->range_bits >= 0) {
int cmpWith = specs->extension
? specs->extension - 1 : specs->map_count;
if(value >= cmpWith)
inext = 1;
}
if(ct->flags & APC_EXTENSIBLE) {
if(per_put_few_bits(po, inext, 0))
_ASN_ENCODE_FAILED;
ct = 0;
} else if(inext) {
_ASN_ENCODE_FAILED;
}
if(ct && ct->range_bits >= 0) {
if(per_put_few_bits(po, value, ct->range_bits))
_ASN_ENCODE_FAILED;
_ASN_ENCODED_OK(er);
}
if(!specs->extension)
_ASN_ENCODE_FAILED;
/*
* X.691, #10.6: normally small non-negative whole number;
*/
if(uper_put_nsnnwn(po, value - (specs->extension - 1)))
_ASN_ENCODE_FAILED;
_ASN_ENCODED_OK(er);
}
/*-
* Copyright (c) 2004, 2005 Lev Walkin <vlm@lionet.info>. All rights reserved.
* Copyright (c) 2004, 2005, 2006 Lev Walkin <vlm@lionet.info>.
* All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
/*
......@@ -22,6 +23,7 @@ extern asn_TYPE_descriptor_t asn_DEF_NativeEnumerated;
xer_type_encoder_f NativeEnumerated_encode_xer;
per_type_decoder_f NativeEnumerated_decode_uper;
per_type_encoder_f NativeEnumerated_encode_uper;
#ifdef __cplusplus
}
......
/*-
* Copyright (c) 2004, 2005 Lev Walkin <vlm@lionet.info>. All rights reserved.
* Copyright (c) 2004, 2005, 2006 Lev Walkin <vlm@lionet.info>.
* All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
/*
......@@ -29,6 +30,7 @@ asn_TYPE_descriptor_t asn_DEF_NativeInteger = {
NativeInteger_decode_xer,
NativeInteger_encode_xer,
NativeInteger_decode_uper, /* Unaligned PER decoder */
NativeInteger_encode_uper, /* Unaligned PER encoder */
0, /* Use generic outmost tag fetcher */
asn_DEF_NativeInteger_tags,
sizeof(asn_DEF_NativeInteger_tags) / sizeof(asn_DEF_NativeInteger_tags[0]),
......@@ -253,6 +255,27 @@ NativeInteger_decode_uper(asn_codec_ctx_t *opt_codec_ctx,
return rval;
}
asn_enc_rval_t
NativeInteger_encode_uper(asn_TYPE_descriptor_t *td,
asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) {
asn_enc_rval_t er;
long native;
INTEGER_t tmpint;
if(!sptr) _ASN_ENCODE_FAILED;
native = *(long *)sptr;
ASN_DEBUG("Encoding NativeInteger %s %ld (UPER)", td->name, native);
memset(&tmpint, 0, sizeof(tmpint));
if(asn_long2INTEGER(&tmpint, native))
_ASN_ENCODE_FAILED;
er = INTEGER_encode_uper(td, constraints, &tmpint, po);
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_INTEGER, &tmpint);
return er;
}
/*
* INTEGER specific human-readable output.
*/
......
......@@ -28,6 +28,7 @@ der_type_encoder_f NativeInteger_encode_der;
xer_type_decoder_f NativeInteger_decode_xer;
xer_type_encoder_f NativeInteger_encode_xer;
per_type_decoder_f NativeInteger_decode_uper;
per_type_encoder_f NativeInteger_encode_uper;
#ifdef __cplusplus
}
......
......@@ -29,7 +29,7 @@ asn_TYPE_descriptor_t asn_DEF_NativeReal = {
NativeReal_encode_der,
NativeReal_decode_xer,
NativeReal_encode_xer,
0,
0, 0,
0, /* Use generic outmost tag fetcher */
asn_DEF_NativeReal_tags,
sizeof(asn_DEF_NativeReal_tags) / sizeof(asn_DEF_NativeReal_tags[0]),
......
......@@ -22,7 +22,7 @@ asn_TYPE_descriptor_t asn_DEF_NumericString = {
OCTET_STRING_encode_der,
OCTET_STRING_decode_xer_utf8,
OCTET_STRING_encode_xer_utf8,
0,
0, 0,
0, /* Use generic outmost tag fetcher */
asn_DEF_NumericString_tags,
sizeof(asn_DEF_NumericString_tags)
......
......@@ -23,7 +23,7 @@ asn_TYPE_descriptor_t asn_DEF_OBJECT_IDENTIFIER = {
der_encode_primitive,
OBJECT_IDENTIFIER_decode_xer,
OBJECT_IDENTIFIER_encode_xer,
0,
0, 0,
0, /* Use generic outmost tag fetcher */
asn_DEF_OBJECT_IDENTIFIER_tags,
sizeof(asn_DEF_OBJECT_IDENTIFIER_tags)
......@@ -425,6 +425,7 @@ OBJECT_IDENTIFIER_set_single_arc(uint8_t *arcbuf, const void *arcval, unsigned i
* The following conditions must hold:
* assert(arcval);
* assert(arcval_size > 0);
* assert(arcval_size <= 16);
* assert(arcbuf);
*/
#ifdef WORDS_BIGENDIAN
......@@ -437,12 +438,7 @@ OBJECT_IDENTIFIER_set_single_arc(uint8_t *arcbuf, const void *arcval, unsigned i
unsigned int cache;
uint8_t *bp = arcbuf;
int bits;
#ifdef __GNUC__
uint8_t buffer[arcval_size];
#else
uint8_t *buffer = alloca(arcval_size);
if(!buffer) { errno = ENOMEM; return -1; }
#endif
uint8_t buffer[16];
if(isLittleEndian && !prepared_order) {
const uint8_t *a = (const unsigned char *)arcval + arcval_size - 1;
......@@ -502,7 +498,9 @@ OBJECT_IDENTIFIER_set_arcs(OBJECT_IDENTIFIER_t *oid, const void *arcs, unsigned
unsigned size;
unsigned i;
if(!oid || !arcs || arc_type_size < 1 || arc_slots < 2) {
if(!oid || !arcs || arc_type_size < 1
|| arc_type_size > 16
|| arc_slots < 2) {
errno = EINVAL;
return -1;
}
......@@ -586,17 +584,8 @@ OBJECT_IDENTIFIER_set_arcs(OBJECT_IDENTIFIER_t *oid, const void *arcs, unsigned
*/
{
uint8_t *tp;
#ifdef __GNUC__
uint8_t first_value[1 + arc_type_size]; /* of two arcs */
uint8_t *fv = first_value;
#else
uint8_t *first_value = alloca(1 + arc_type_size);
uint8_t first_value[1 + 16]; /* of two arcs */
uint8_t *fv = first_value;
if(!first_value) {
errno = ENOMEM;
return -1;
}
#endif
/*
* Simulate first_value = arc0 * 40 + arc1;
......
......@@ -33,6 +33,7 @@ asn_TYPE_descriptor_t asn_DEF_OCTET_STRING = {
OCTET_STRING_decode_xer_hex,
OCTET_STRING_encode_xer,
OCTET_STRING_decode_uper, /* Unaligned PER decoder */
OCTET_STRING_encode_uper, /* Unaligned PER encoder */
0, /* Use generic outmost tag fetcher */
asn_DEF_OCTET_STRING_tags,
sizeof(asn_DEF_OCTET_STRING_tags)
......@@ -1297,6 +1298,103 @@ OCTET_STRING_decode_uper(asn_codec_ctx_t *opt_codec_ctx,
return rval;
}
asn_enc_rval_t
OCTET_STRING_encode_uper(asn_TYPE_descriptor_t *td,
asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) {
asn_OCTET_STRING_specifics_t *specs = td->specifics
? (asn_OCTET_STRING_specifics_t *)td->specifics
: &asn_DEF_OCTET_STRING_specs;
asn_per_constraint_t *ct = constraints ? &constraints->size
: (td->per_constraints
? &td->per_constraints->size
: &asn_DEF_OCTET_STRING_constraint);
const BIT_STRING_t *st = (const BIT_STRING_t *)sptr;
int unit_bits = (specs->subvariant != 1) * 7 + 1;
asn_enc_rval_t er;
int ct_extensible = ct->flags & APC_EXTENSIBLE;
int inext = 0; /* Lies not within extension root */
int sizeinunits = st->size;
const uint8_t *buf;
int ret;
if(!st || !st->buf)
_ASN_ENCODE_FAILED;
if(unit_bits == 1) {
ASN_DEBUG("BIT STRING of %d bytes, %d bits unused",
sizeinunits, st->bits_unused);
sizeinunits = sizeinunits * 8 - (st->bits_unused & 0x07);
}
ASN_DEBUG("Encoding %s into %d units",
td->name, sizeinunits);
/* Figure out wheter size lies within PER visible consrtaint */
if(ct->effective_bits >= 0) {
if(sizeinunits < ct->lower_bound
|| sizeinunits > ct->upper_bound) {
if(ct_extensible) {
ct = &asn_DEF_OCTET_STRING_constraint;
inext = 1;
} else
_ASN_ENCODE_FAILED;
}
} else {
inext = 0;
}
if(ct_extensible) {
/* Declare whether length is [not] within extension root */
if(per_put_few_bits(po, inext, 1))
_ASN_ENCODE_FAILED;
}
/* X.691, #16.5: zero-length encoding */
/* X.691, #16.6: short fixed length encoding (up to 2 octets) */
/* X.691, #16.7: long fixed length encoding (up to 64K octets) */
if(ct->effective_bits >= 0) {
ASN_DEBUG("Encoding %d bytes (%ld), length in %d bits",
st->size, sizeinunits - ct->lower_bound,
ct->effective_bits);
ret = per_put_few_bits(po, sizeinunits - ct->lower_bound,
ct->effective_bits);
if(ret) _ASN_ENCODE_FAILED;
ret = per_put_many_bits(po, st->buf, sizeinunits);
if(ret) _ASN_ENCODE_FAILED;
_ASN_ENCODED_OK(er);
}
ASN_DEBUG("Encoding %d bytes", st->size);
if(sizeinunits == 0) {
if(uper_put_length(po, 0))
_ASN_ENCODE_FAILED;
_ASN_ENCODED_OK(er);
}
buf = st->buf;
while(sizeinunits) {
ssize_t maySave = uper_put_length(po, sizeinunits);
if(maySave < 0) _ASN_ENCODE_FAILED;
ASN_DEBUG("Encoding %d of %d", maySave, sizeinunits);
ret = per_put_many_bits(po, buf, maySave);
if(ret) _ASN_ENCODE_FAILED;
if(unit_bits == 1)
buf += maySave >> 3;
else
buf += maySave;
sizeinunits -= maySave;
assert(!(maySave & 0x07) || !sizeinunits);
}
_ASN_ENCODED_OK(er);
}
int
OCTET_STRING_print(asn_TYPE_descriptor_t *td, const void *sptr, int ilevel,
asn_app_consume_bytes_f *cb, void *app_key) {
......
......@@ -31,6 +31,7 @@ xer_type_decoder_f OCTET_STRING_decode_xer_utf8; /* ASCII/UTF-8 */
xer_type_encoder_f OCTET_STRING_encode_xer;
xer_type_encoder_f OCTET_STRING_encode_xer_utf8;
per_type_decoder_f OCTET_STRING_decode_uper;
per_type_encoder_f OCTET_STRING_encode_uper;
/******************************
* Handy conversion routines. *
......
......@@ -22,7 +22,7 @@ asn_TYPE_descriptor_t asn_DEF_ObjectDescriptor = {
OCTET_STRING_encode_der,
OCTET_STRING_decode_xer_utf8,
OCTET_STRING_encode_xer_utf8,
0,
0, 0,
0, /* Use generic outmost tag fetcher */
asn_DEF_ObjectDescriptor_tags,
sizeof(asn_DEF_ObjectDescriptor_tags)
......
......@@ -22,7 +22,7 @@ asn_TYPE_descriptor_t asn_DEF_PrintableString = {
OCTET_STRING_encode_der,
OCTET_STRING_decode_xer_utf8,
OCTET_STRING_encode_xer_utf8,
0,
0, 0,
0, /* Use generic outmost tag fetcher */
asn_DEF_PrintableString_tags,
sizeof(asn_DEF_PrintableString_tags)
......
......@@ -42,7 +42,7 @@ asn_TYPE_descriptor_t asn_DEF_REAL = {
der_encode_primitive,
REAL_decode_xer,
REAL_encode_xer,
0,
0, 0,
0, /* Use generic outmost tag fetcher */
asn_DEF_REAL_tags,
sizeof(asn_DEF_REAL_tags) / sizeof(asn_DEF_REAL_tags[0]),
......
......@@ -25,7 +25,7 @@ asn_TYPE_descriptor_t asn_DEF_RELATIVE_OID = {
der_encode_primitive,
RELATIVE_OID_decode_xer,
RELATIVE_OID_encode_xer,
0,
0, 0,
0, /* Use generic outmost tag fetcher */
asn_DEF_RELATIVE_OID_tags,
sizeof(asn_DEF_RELATIVE_OID_tags)
......
......@@ -22,7 +22,7 @@ asn_TYPE_descriptor_t asn_DEF_T61String = {
OCTET_STRING_encode_der,
OCTET_STRING_decode_xer_hex,
OCTET_STRING_encode_xer,
0,
0, 0,
0, /* Use generic outmost tag fetcher */
asn_DEF_T61String_tags,
sizeof(asn_DEF_T61String_tags)
......
......@@ -22,7 +22,7 @@ asn_TYPE_descriptor_t asn_DEF_TeletexString = {
OCTET_STRING_encode_der,
OCTET_STRING_decode_xer_hex,
OCTET_STRING_encode_xer,
0,
0, 0,
0, /* Use generic outmost tag fetcher */
asn_DEF_TeletexString_tags,
sizeof(asn_DEF_TeletexString_tags)
......
......@@ -28,7 +28,7 @@ asn_TYPE_descriptor_t asn_DEF_UTCTime = {
OCTET_STRING_encode_der, /* Implemented in terms of OCTET STRING */
OCTET_STRING_decode_xer_utf8,
UTCTime_encode_xer,
0,
0, 0,
0, /* Use generic outmost tag fetcher */
asn_DEF_UTCTime_tags,
sizeof(asn_DEF_UTCTime_tags)
......
......@@ -22,7 +22,7 @@ asn_TYPE_descriptor_t asn_DEF_UTF8String = {
OCTET_STRING_encode_der,
OCTET_STRING_decode_xer_utf8,
OCTET_STRING_encode_xer_utf8,
0,
0, 0,
0, /* Use generic outmost tag fetcher */
asn_DEF_UTF8String_tags,
sizeof(asn_DEF_UTF8String_tags)
......
......@@ -23,7 +23,7 @@ asn_TYPE_descriptor_t asn_DEF_UniversalString = {
OCTET_STRING_encode_der,
UniversalString_decode_xer, /* Convert from UTF-8 */
UniversalString_encode_xer, /* Convert into UTF-8 */
0,
0, 0,
0, /* Use generic outmost tag fetcher */
asn_DEF_UniversalString_tags,
sizeof(asn_DEF_UniversalString_tags)
......
......@@ -22,7 +22,7 @@ asn_TYPE_descriptor_t asn_DEF_VideotexString = {
OCTET_STRING_encode_der,
OCTET_STRING_decode_xer_hex,
OCTET_STRING_encode_xer,
0,
0, 0,
0, /* Use generic outmost tag fetcher */
asn_DEF_VideotexString_tags,
sizeof(asn_DEF_VideotexString_tags)
......
......@@ -22,7 +22,7 @@ asn_TYPE_descriptor_t asn_DEF_VisibleString = {
OCTET_STRING_encode_der,
OCTET_STRING_decode_xer_utf8,
OCTET_STRING_encode_xer_utf8,
0,
0, 0,
0, /* Use generic outmost tag fetcher */
asn_DEF_VisibleString_tags,
sizeof(asn_DEF_VisibleString_tags)
......
/*-
* Copyright (c) 2003, 2004, 2005 Lev Walkin <vlm@lionet.info>.
/*
* Copyright (c) 2003, 2004, 2005, 2006 Lev Walkin <vlm@lionet.info>.
* All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
......@@ -363,6 +363,8 @@ CHOICE_encode_der(asn_TYPE_descriptor_t *td, void *sptr,
size_t computed_size = 0;
int present;
if(!sptr) _ASN_ENCODE_FAILED;
ASN_DEBUG("%s %s as CHOICE",
cb?"Encoding":"Estimating", td->name);
......@@ -892,6 +894,82 @@ CHOICE_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
return rv;
}
asn_enc_rval_t
CHOICE_encode_uper(asn_TYPE_descriptor_t *td,
asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) {
asn_CHOICE_specifics_t *specs = (asn_CHOICE_specifics_t *)td->specifics;
asn_TYPE_member_t *elm; /* CHOICE's element */
asn_per_constraint_t *ct;
void *memb_ptr;
int present;
if(!sptr) _ASN_ENCODE_FAILED;
ASN_DEBUG("Encoding %s as CHOICE", td->name);
if(constraints) ct = &constraints->value;
else if(td->per_constraints) ct = &td->per_constraints->value;
else ct = 0;
present = _fetch_present_idx(sptr,
specs->pres_offset, specs->pres_size);
/*
* If the structure was not initialized properly, it cannot be encoded:
* can't deduce what to encode in the choice type.
*/
if(present <= 0 || present > td->elements_count)
_ASN_ENCODE_FAILED;
else
present--;
/* Adjust if canonical order is different from natural order */
if(specs->canonical_order)
present = specs->canonical_order[present];
ASN_DEBUG("Encoding %s CHOICE element %d", td->name, present);
if(ct && ct->range_bits >= 0) {
if(present < ct->lower_bound
|| present > ct->upper_bound) {
if(ct->flags & APC_EXTENSIBLE) {
if(per_put_few_bits(po, 1, 1))
_ASN_ENCODE_FAILED;
} else {
_ASN_ENCODE_FAILED;
}
ct = 0;
}
}
if(ct && ct->flags & APC_EXTENSIBLE)
if(per_put_few_bits(po, 0, 1))
_ASN_ENCODE_FAILED;
if(ct && ct->range_bits >= 0) {
if(per_put_few_bits(po, present, ct->range_bits))
_ASN_ENCODE_FAILED;
} else {
if(specs->ext_start == -1)
_ASN_ENCODE_FAILED;
if(uper_put_nsnnwn(po, present - specs->ext_start))
_ASN_ENCODE_FAILED;
ASN_DEBUG("NOT IMPLEMENTED YET");
_ASN_ENCODE_FAILED;
}
elm = &td->elements[present];
if(elm->flags & ATF_POINTER) {
/* Member is a pointer to another structure */
memb_ptr = *(void **)((char *)sptr + elm->memb_offset);
if(!memb_ptr) _ASN_ENCODE_FAILED;
} else {
memb_ptr = (char *)sptr + elm->memb_offset;
}
return elm->type->uper_encoder(elm->type, elm->per_constraints,
memb_ptr, po);
}
int
CHOICE_print(asn_TYPE_descriptor_t *td, const void *sptr, int ilevel,
......
......@@ -47,6 +47,7 @@ der_type_encoder_f CHOICE_encode_der;
xer_type_decoder_f CHOICE_decode_xer;
xer_type_encoder_f CHOICE_encode_xer;
per_type_decoder_f CHOICE_decode_uper;
per_type_encoder_f CHOICE_encode_uper;
asn_outmost_tag_f CHOICE_outmost_tag;
#ifdef __cplusplus
......
/*-
* Copyright (c) 2003, 2004, 2005 Lev Walkin <vlm@lionet.info>.
* Copyright (c) 2003, 2004, 2005, 2006 Lev Walkin <vlm@lionet.info>.
* All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
......@@ -1097,7 +1097,7 @@ SEQUENCE_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
/* This element is not present */
if(elm->default_value) {
/* Fill-in DEFAULT */
if(elm->default_value(memb_ptr2)) {
if(elm->default_value(1, memb_ptr2)) {
FREEMEM(opres);
_ASN_DECODE_FAILED;
}
......@@ -1137,14 +1137,15 @@ SEQUENCE_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
/* Fetch the pointer to this member */
if(elm->flags & ATF_POINTER) {
memb_ptr2 = (void **)((char *)st + elm->memb_offset);
memb_ptr2 = (void **)((char *)st
+ elm->memb_offset);
} else {
memb_ptr = (char *)st + elm->memb_offset;
memb_ptr2 = &memb_ptr;
}
/* Set default value */
if(elm->default_value(memb_ptr2)) {
if(elm->default_value(1, memb_ptr2)) {
FREEMEM(opres);
_ASN_DECODE_FAILED;
}
......@@ -1157,3 +1158,92 @@ SEQUENCE_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
return rv;
}
asn_enc_rval_t
SEQUENCE_encode_uper(asn_TYPE_descriptor_t *td,
asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) {
asn_SEQUENCE_specifics_t *specs
= (asn_SEQUENCE_specifics_t *)td->specifics;
asn_enc_rval_t er;
int edx;
int i;
(void)constraints;
if(!sptr)
_ASN_ENCODE_FAILED;
er.encoded = 0;
ASN_DEBUG("Encoding %s as SEQUENCE (UPER)", td->name);
if(specs->ext_before >= 0)
_ASN_ENCODE_FAILED; /* We don't encode extensions yet */
/* Encode a presence bitmap */
for(i = 0; i < specs->roms_count; i++) {
void *memb_ptr; /* Pointer to the member */
void **memb_ptr2; /* Pointer to that pointer */
edx = specs->oms[i];
asn_TYPE_member_t *elm = &td->elements[edx];
int present;
/* Fetch the pointer to this member */
if(elm->flags & ATF_POINTER) {
memb_ptr2 = (void **)((char *)sptr + elm->memb_offset);
present = (*memb_ptr2 != 0);
} else {
memb_ptr = (void *)((char *)sptr + elm->memb_offset);
memb_ptr2 = &memb_ptr;
present = 1;
}
/* Eliminate default values */
if(present && elm->default_value
&& elm->default_value(0, memb_ptr2) == 1)
present = 0;
ASN_DEBUG("Element %s %s %s->%s is %s",
elm->flags & ATF_POINTER ? "ptr" : "inline",
elm->default_value ? "def" : "wtv",
td->name, elm->name, present ? "present" : "absent");
if(per_put_few_bits(po, present, 1))
_ASN_ENCODE_FAILED;
}
/*
* Get the sequence ROOT elements.
*/
for(edx = 0; edx < ((specs->ext_before < 0)
? td->elements_count : specs->ext_before + 1); edx++) {
asn_TYPE_member_t *elm = &td->elements[edx];
void *memb_ptr; /* Pointer to the member */
void **memb_ptr2; /* Pointer to that pointer */
/* Fetch the pointer to this member */
if(elm->flags & ATF_POINTER) {
memb_ptr2 = (void **)((char *)sptr + elm->memb_offset);
if(!*memb_ptr2) {
ASN_DEBUG("Element %s %d not present",
elm->name, edx);
if(elm->optional)
continue;
/* Mandatory element is missing */
_ASN_ENCODE_FAILED;
}
} else {
memb_ptr = (void *)((char *)sptr + elm->memb_offset);
memb_ptr2 = &memb_ptr;
}
/* Eliminate default values */
if(elm->default_value && elm->default_value(0, memb_ptr2) == 1)
continue;
er = elm->type->uper_encoder(elm->type, elm->per_constraints,
*memb_ptr2, po);
if(er.encoded == -1)
return er;
}
_ASN_ENCODED_OK(er);
}
......@@ -51,6 +51,7 @@ der_type_encoder_f SEQUENCE_encode_der;
xer_type_decoder_f SEQUENCE_decode_xer;
xer_type_encoder_f SEQUENCE_encode_xer;
per_type_decoder_f SEQUENCE_decode_uper;
per_type_encoder_f SEQUENCE_encode_uper;
#ifdef __cplusplus
}
......
/*-
* Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
* Copyright (c) 2003, 2004, 2006 Lev Walkin <vlm@lionet.info>.
* All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
#include <asn_internal.h>
......@@ -139,3 +140,69 @@ cb_failed:
_ASN_ENCODE_FAILED;
}
asn_enc_rval_t
SEQUENCE_OF_encode_uper(asn_TYPE_descriptor_t *td,
asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) {
asn_anonymous_sequence_ *list;
asn_per_constraint_t *ct;
asn_enc_rval_t er;
asn_TYPE_member_t *elm = td->elements;
int seq;
if(!sptr) _ASN_ENCODE_FAILED;
list = _A_SEQUENCE_FROM_VOID(sptr);
er.encoded = 0;
ASN_DEBUG("Encoding %s as SEQUENCE OF (%d)", td->name, list->count);
if(constraints) ct = &constraints->size;
else if(td->per_constraints) ct = &td->per_constraints->size;
else ct = 0;
/* If extensible constraint, check if size is in root */
if(ct) {
int not_in_root = (list->count < ct->lower_bound
|| list->count > ct->upper_bound);
ASN_DEBUG("lb %ld ub %ld %s",
ct->lower_bound, ct->upper_bound,
ct->flags & APC_EXTENSIBLE ? "ext" : "fix");
if(ct->flags & APC_EXTENSIBLE) {
/* Declare whether size is in extension root */
if(per_put_few_bits(po, not_in_root, 1))
_ASN_ENCODE_FAILED;
if(not_in_root) ct = 0;
} else if(not_in_root && ct->effective_bits >= 0)
_ASN_ENCODE_FAILED;
}
if(ct && ct->effective_bits >= 0) {
/* X.691, #19.5: No length determinant */
if(per_put_few_bits(po, list->count - ct->lower_bound,
ct->effective_bits))
_ASN_ENCODE_FAILED;
}
for(seq = -1; seq < list->count;) {
ssize_t mayEncode;
if(seq < 0) seq = 0;
if(ct && ct->effective_bits >= 0) {
mayEncode = list->count;
} else {
mayEncode = uper_put_length(po, list->count - seq);
if(mayEncode < 0) _ASN_ENCODE_FAILED;
}
while(mayEncode--) {
void *memb_ptr = list->array[seq++];
if(!memb_ptr) _ASN_ENCODE_FAILED;
er = elm->type->uper_encoder(elm->type,
elm->per_constraints, memb_ptr, po);
if(er.encoded == -1)
_ASN_ENCODE_FAILED;
}
}
_ASN_ENCODED_OK(er);
}
......@@ -24,6 +24,7 @@ extern "C" {
#define SEQUENCE_OF_decode_uper SET_OF_decode_uper
der_type_encoder_f SEQUENCE_OF_encode_der;
xer_type_encoder_f SEQUENCE_OF_encode_xer;
per_type_encoder_f SEQUENCE_OF_encode_uper;
#ifdef __cplusplus
}
......
......@@ -33,6 +33,7 @@ der_type_encoder_f SET_OF_encode_der;
xer_type_decoder_f SET_OF_decode_xer;
xer_type_encoder_f SET_OF_encode_xer;
per_type_decoder_f SET_OF_decode_uper;
per_type_encoder_f SET_OF_encode_uper;
#ifdef __cplusplus
}
......
/*-
* Copyright (c) 2003, 2004, 2005 Lev Walkin <vlm@lionet.info>.
* Copyright (c) 2003, 2004, 2005, 2006 Lev Walkin <vlm@lionet.info>.
* All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
......@@ -40,6 +40,7 @@ typedef struct asn_struct_ctx_s {
#include <xer_decoder.h> /* Decoder of XER (XML, text) */
#include <xer_encoder.h> /* Encoder into XER (XML, text) */
#include <per_decoder.h> /* Packet Encoding Rules decoder */
#include <per_encoder.h> /* Packet Encoding Rules encoder */
#include <constraints.h> /* Subtype constraints support */
/*
......@@ -97,6 +98,7 @@ typedef struct asn_TYPE_descriptor_s {
xer_type_decoder_f *xer_decoder; /* Generic XER decoder */
xer_type_encoder_f *xer_encoder; /* [Canonical] XER encoder */
per_type_decoder_f *uper_decoder; /* Unaligned PER decoder */
per_type_encoder_f *uper_encoder; /* Unaligned PER encoder */
/***********************************************************************
* Internally useful members. Not to be used by applications directly. *
......@@ -144,7 +146,7 @@ typedef struct asn_TYPE_member_s {
asn_TYPE_descriptor_t *type; /* Member type descriptor */
asn_constr_check_f *memb_constraints; /* Constraints validator */
asn_per_constraints_t *per_constraints; /* PER compiled constraints */
int (*default_value)(void **sptr); /* DEFAULT <value> */
int (*default_value)(int setval, void **sptr); /* DEFAULT <value> */
char *name; /* ASN.1 identifier of the element */
} asn_TYPE_member_t;
......
......@@ -52,20 +52,19 @@ static int encode_to_buffer_cb(const void *buffer, size_t size, void *key) {
*/
asn_enc_rval_t
der_encode_to_buffer(asn_TYPE_descriptor_t *type_descriptor, void *struct_ptr,
void *buffer, size_t *buffer_size) {
void *buffer, size_t buffer_size) {
enc_to_buf_arg arg;
asn_enc_rval_t ec;
arg.buffer = buffer;
arg.left = *buffer_size;
arg.left = buffer_size;
ec = type_descriptor->der_encoder(type_descriptor,
struct_ptr, /* Pointer to the destination structure */
0, 0, encode_to_buffer_cb, &arg);
if(ec.encoded != -1) {
assert(ec.encoded == (ssize_t)(*buffer_size - arg.left));
assert(ec.encoded == (ssize_t)(buffer_size - arg.left));
/* Return the encoded contents size */
*buffer_size = ec.encoded;
}
return ec;
}
......
......@@ -27,7 +27,7 @@ asn_enc_rval_t der_encode_to_buffer(
struct asn_TYPE_descriptor_s *type_descriptor,
void *struct_ptr, /* Structure to be encoded */
void *buffer, /* Pre-allocated buffer */
size_t *buffer_size /* Initial buffer size (max) */
size_t buffer_size /* Initial buffer size (maximum) */
);
/*
......
......@@ -60,6 +60,7 @@ xer_decoder.h xer_decoder.c # XER decoding support
xer_encoder.h xer_encoder.c # XER encoding support
per_support.h per_support.c # PER parsing
per_decoder.h per_decoder.c # PER decoding support
per_encoder.h per_encoder.c # PER encoding support
#asn-decoder-template.c # Template for quick decoder creation
CODEC-PER: # THIS IS A SPECIAL SECTION
#include <asn_application.h>
#include <asn_internal.h>
#include <per_encoder.h>
/* Flush partially filled buffer */
static int _uper_encode_flush_outp(asn_per_outp_t *po);
asn_enc_rval_t
uper_encode(asn_TYPE_descriptor_t *td, void *sptr, asn_app_consume_bytes_f *cb, void *app_key) {
asn_per_outp_t po;
asn_enc_rval_t er;
/*
* Invoke type-specific encoder.
*/
if(!td || !td->uper_encoder)
_ASN_ENCODE_FAILED; /* PER is not compiled in */
po.buffer = po.tmpspace;
po.nboff = 0;
po.nbits = 8 * sizeof(po.tmpspace);
po.outper = cb;
po.op_key = app_key;
er = td->uper_encoder(td, 0, sptr, &po);
if(er.encoded != -1 && _uper_encode_flush_outp(&po))
_ASN_ENCODE_FAILED;
return er;
}
/*
* Argument type and callback necessary for uper_encode_to_buffer().
*/
typedef struct enc_to_buf_arg {
void *buffer;
size_t left;
} enc_to_buf_arg;
static int encode_to_buffer_cb(const void *buffer, size_t size, void *key) {
enc_to_buf_arg *arg = (enc_to_buf_arg *)key;
if(arg->left < size)
return -1; /* Data exceeds the available buffer size */
memcpy(arg->buffer, buffer, size);
arg->buffer = ((char *)arg->buffer) + size;
arg->left -= size;
return 0;
}
asn_enc_rval_t
uper_encode_to_buffer(asn_TYPE_descriptor_t *td, void *sptr, void *buffer, size_t buffer_size) {
enc_to_buf_arg key;
asn_enc_rval_t er;
/*
* Invoke type-specific encoder.
*/
if(!td || !td->uper_encoder)
_ASN_ENCODE_FAILED; /* PER is not compiled in */
key.buffer = buffer;
key.left = buffer_size;
ASN_DEBUG("Encoding \"%s\" using UNALIGNED PER", td->name);
er = uper_encode(td, sptr, encode_to_buffer_cb, &key);
if(er.encoded != -1)
er.encoded = buffer_size - key.left;
return er;
}
static int
_uper_encode_flush_outp(asn_per_outp_t *po) {
uint8_t *buf;
if(po->nboff == 0 && po->buffer == po->tmpspace)
return 0;
buf = po->buffer + (po->nboff >> 3);
/* Make sure we account for the last, partially filled */
if(po->nboff & 0x07) {
buf[0] &= 0xff << (8 - (po->nboff & 0x07));
buf++;
}
return po->outper(po->tmpspace, buf - po->tmpspace, po->op_key);
}
/*-
* Copyright (c) 2006 Lev Walkin <vlm@lionet.info>. All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
#ifndef _PER_ENCODER_H_
#define _PER_ENCODER_H_
#include <asn_application.h>
#include <per_support.h>
#ifdef __cplusplus
extern "C" {
#endif
struct asn_TYPE_descriptor_s; /* Forward declaration */
/*
* Unaligned PER encoder of any ASN.1 type. May be invoked by the application.
*/
asn_enc_rval_t uper_encode(struct asn_TYPE_descriptor_s *type_descriptor,
void *struct_ptr, /* Structure to be encoded */
asn_app_consume_bytes_f *consume_bytes_cb, /* Data collector */
void *app_key /* Arbitrary callback argument */
);
/* A variant of uper_encode() which encodes data into the existing buffer */
asn_enc_rval_t uper_encode_to_buffer(
struct asn_TYPE_descriptor_s *type_descriptor,
void *struct_ptr, /* Structure to be encoded */
void *buffer, /* Pre-allocated buffer */
size_t buffer_size /* Initial buffer size (max) */
);
/*
* Type of the generic PER encoder function.
*/
typedef asn_enc_rval_t (per_type_encoder_f)(
struct asn_TYPE_descriptor_s *type_descriptor,
asn_per_constraints_t *constraints,
void *struct_ptr,
asn_per_outp_t *per_output
);
#ifdef __cplusplus
}
#endif
#endif /* _PER_ENCODER_H_ */
/*
* Copyright (c) 2005 Lev Walkin <vlm@lionet.info>. All rights reserved.
* Copyright (c) 2005, 2006 Lev Walkin <vlm@lionet.info>. All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
#include <asn_system.h>
......@@ -80,7 +80,7 @@ per_get_many_bits(asn_per_data_t *pd, uint8_t *dst, int alright, int nbits) {
} else {
value = per_get_few_bits(pd, nbits);
if(value < 0) return -1;
if(nbits & 7) { /* implies alright */
if(nbits & 7) { /* implies left alignment */
value <<= 8 - (nbits & 7),
nbits += 8 - (nbits & 7);
if(nbits > 24)
......@@ -150,3 +150,161 @@ uper_get_nsnnwn(asn_per_data_t *pd) {
return value;
}
/*
* Put the normally small non-negative whole number.
* X.691, #10.6
*/
int
uper_put_nsnnwn(asn_per_outp_t *po, int n) {
int bytes;
if(n <= 63) {
if(n < 0) return -1;
return per_put_few_bits(po, n, 7);
}
if(n < 256)
bytes = 1;
else if(n < 65536)
bytes = 2;
else if(n < 256 * 65536)
bytes = 3;
else
return -1; /* This is not a "normally small" value */
if(per_put_few_bits(po, bytes, 8))
return -1;
return per_put_few_bits(po, n, 8 * bytes);
}
/*
* Put a small number of bits (<= 31).
*/
int
per_put_few_bits(asn_per_outp_t *po, uint32_t bits, int obits) {
size_t off; /* Next after last bit offset */
size_t omsk; /* Existing last byte meaningful bits mask */
uint8_t *buf;
if(obits <= 0 || obits >= 32) return obits ? -1 : 0;
/*
* Normalize position indicator.
*/
if(po->nboff >= 8) {
po->buffer += (po->nboff >> 3);
po->nbits -= (po->nboff & ~0x07);
po->nboff &= 0x07;
}
/*
* Flush whole-bytes output, if necessary.
*/
if(po->nboff + obits > po->nbits) {
int complete_bytes = (po->buffer - po->tmpspace);
if(po->outper(po->buffer, complete_bytes, po->op_key) < 0)
return -1;
if(po->nboff)
po->tmpspace[0] = po->buffer[0];
po->buffer = po->tmpspace;
po->nbits = 8 * sizeof(po->tmpspace);
}
/*
* Now, due to sizeof(tmpspace), we are guaranteed large enough space.
*/
buf = po->buffer;
omsk = ~((1 << (8 - po->nboff)) - 1);
off = (po->nboff += obits);
/* Clear data of debris before meaningful bits */
bits &= (((uint32_t)1 << obits) - 1);
ASN_DEBUG("[PER out %d %u/%x (t=%d,o=%d) %x&%x=%x]", obits, bits, bits,
po->nboff - obits, off, buf[0], omsk&0xff, buf[0] & omsk);
if(off <= 8) /* Completely within 1 byte */
bits <<= (8 - off),
buf[0] = (buf[0] & omsk) | bits;
else if(off <= 16)
bits <<= (16 - off),
buf[0] = (buf[0] & omsk) | (bits >> 8),
buf[1] = bits;
else if(off <= 24)
bits <<= (24 - off),
buf[0] = (buf[0] & omsk) | (bits >> 16),
buf[1] = bits >> 8,
buf[2] = bits;
else if(off <= 31)
bits <<= (32 - off),
buf[0] = (buf[0] & omsk) | (bits >> 24),
buf[1] = bits >> 16,
buf[2] = bits >> 8,
buf[3] = bits;
else {
ASN_DEBUG("->[PER out split %d]", obits);
per_put_few_bits(po, bits >> 8, 24);
per_put_few_bits(po, bits, obits - 24);
ASN_DEBUG("<-[PER out split %d]", obits);
}
ASN_DEBUG("[PER out %u/%x => %02x buf+%d]",
bits, bits, buf[0], po->buffer - po->tmpspace);
return 0;
}
/*
* Output a large number of bits.
*/
int
per_put_many_bits(asn_per_outp_t *po, const uint8_t *src, int nbits) {
while(nbits) {
uint32_t value;
if(nbits >= 24) {
value = (src[0] << 16) | (src[1] << 8) | src[2];
src += 3;
nbits -= 24;
if(per_put_few_bits(po, value, 24))
return -1;
} else {
value = src[0];
if(nbits > 8)
value = (value << 8) | src[1];
if(nbits > 16)
value = (value << 8) | src[2];
if(nbits & 0x07)
value >>= (8 - (nbits & 0x07));
if(per_put_few_bits(po, value, nbits))
return -1;
break;
}
}
return 0;
}
/*
* Put the length "n" (or part of it) into the stream.
*/
ssize_t
uper_put_length(asn_per_outp_t *po, size_t length) {
if(length <= 127) /* #10.9.3.6 */
return per_put_few_bits(po, length, 8)
? -1 : (ssize_t)length;
else if(length < 16384) /* #10.9.3.7 */
return per_put_few_bits(po, length|0x8000, 16)
? -1 : (ssize_t)length;
length >>= 14;
if(length > 4) length = 4;
return per_put_few_bits(po, 0xC0 | length, 8)
? -1 : (ssize_t)(length << 14);
}
......@@ -12,7 +12,7 @@ extern "C" {
#endif
/*
* This structure describes a position inside a PER bit stream.
* This structure describes a position inside an incoming PER bit stream.
*/
typedef struct asn_per_data_s {
const uint8_t *buffer; /* Pointer to the octet stream */
......@@ -20,6 +20,18 @@ typedef struct asn_per_data_s {
size_t nbits; /* Number of bits in the stream */
} asn_per_data_t;
/*
* This structure supports forming PER output.
*/
typedef struct asn_per_outp_s {
uint8_t *buffer; /* Pointer into the (tmpspace) */
size_t nboff; /* Bit offset to the meaningful bit */
size_t nbits; /* Number of bits left in (tmpspace) */
uint8_t tmpspace[32]; /* Preliminary storage to hold data */
int (*outper)(const void *data, size_t size, void *op_key);
void *op_key;
} asn_per_outp_t;
/*
* Extract a small number of bits (<= 31) from the specified PER data pointer.
* This function returns -1 if the specified number of bits could not be
......@@ -27,6 +39,9 @@ typedef struct asn_per_data_s {
*/
int32_t per_get_few_bits(asn_per_data_t *per_data, int get_nbits);
/* Output a small number of bits (<= 31) */
int per_put_few_bits(asn_per_outp_t *per_data, uint32_t bits, int obits);
/*
* Extract a large number of bits from the specified PER data pointer.
* This function returns -1 if the specified number of bits could not be
......@@ -35,6 +50,9 @@ int32_t per_get_few_bits(asn_per_data_t *per_data, int get_nbits);
int per_get_many_bits(asn_per_data_t *pd, uint8_t *dst, int right_align,
int get_nbits);
/* Output a large number of bits */
int per_put_many_bits(asn_per_outp_t *po, const uint8_t *src, int put_nbits);
/*
* Get the length "n" from the Unaligned PER stream.
*/
......@@ -42,11 +60,23 @@ ssize_t uper_get_length(asn_per_data_t *pd,
int effective_bound_bits,
int *repeat);
/*
* Put the length "n" to the Unaligned PER stream.
* This function returns the number of units which may be flushed
* in the next units saving iteration.
*/
ssize_t uper_put_length(asn_per_outp_t *po, size_t whole_length);
/*
* Get the normally small non-negative whole number.
*/
ssize_t uper_get_nsnnwn(asn_per_data_t *pd);
/*
* Put the normally small non-negative whole number.
*/
int uper_put_nsnnwn(asn_per_outp_t *po, int n);
#ifdef __cplusplus
}
#endif
......
#include <per_support.c>
#include <assert.h>
int
main() {
static void
check_per_decoding() {
uint8_t buf[] = { 0xB7, 0x19, 0x2F, 0xEE, 0xAD };
uint8_t tmpbuf[10];
int32_t z;
......@@ -119,6 +119,102 @@ main() {
assert(tmpbuf[2] == buf[2]);
assert(tmpbuf[3] == buf[3]);
assert(tmpbuf[4] == buf[4]);
}
static int Ignore(const void *data, size_t size, void *op_key) {
return 0;
}
static void
check_per_encoding() {
asn_per_outp_t po;
po.buffer = po.tmpspace;
po.nboff = 0;
po.nbits = 0;
po.outper = Ignore;
po.op_key = 0;
po.tmpspace[0] = 0xff;
int ret;
ret = per_put_few_bits(&po, 0, 0);
assert(ret == 0);
assert(po.nboff == 0);
assert(po.buffer == po.tmpspace);
assert(po.tmpspace[0] == 0xff);
ret = per_put_few_bits(&po, 0, 1);
assert(ret == 0);
assert(po.nboff == 1);
assert(po.nbits == 8 * sizeof(po.tmpspace));
assert(po.buffer == po.tmpspace);
assert(po.tmpspace[0] == 0x00);
ret = per_put_few_bits(&po, 1, 1);
assert(ret == 0);
assert(po.nboff == 2);
assert(po.nbits == 8 * sizeof(po.tmpspace));
assert(po.buffer == po.tmpspace);
assert(po.tmpspace[0] == 0x40);
ret = per_put_few_bits(&po, 1, 1);
assert(ret == 0);
assert(po.nboff == 3);
assert(po.nbits == 8 * sizeof(po.tmpspace));
assert(po.buffer == po.tmpspace);
assert(po.tmpspace[0] == 0x60);
ret = per_put_few_bits(&po, 15, 5);
assert(ret == 0);
assert(po.nboff == 8);
assert(po.nbits == 8 * sizeof(po.tmpspace));
assert(po.buffer == po.tmpspace);
assert(po.tmpspace[0] == 0x6F);
ret = per_put_few_bits(&po, 0xf0ff, 16);
assert(ret == 0);
assert(po.nboff == 16);
assert(po.nbits == 8 * sizeof(po.tmpspace) - 8);
assert(po.buffer == po.tmpspace + 1);
assert(po.tmpspace[0] == 0x6F);
assert(po.tmpspace[1] == 0xf0);
assert(po.tmpspace[2] == 0xff);
po.nboff--;
ret = per_put_few_bits(&po, 2, 1);
assert(ret == 0);
assert(po.nboff == 8);
assert(po.nbits == 8 * sizeof(po.tmpspace) - 16);
assert(po.buffer == po.tmpspace + 2);
assert(po.tmpspace[0] == 0x6F);
assert(po.tmpspace[1] == 0xf0);
assert(po.tmpspace[2] == 0xfe);
ret = per_put_few_bits(&po, 2, 32);
assert(ret == -1);
ret = per_put_few_bits(&po, 2, -1);
assert(ret == -1);
ret = per_put_few_bits(&po, -1, 31);
assert(ret == 0);
assert(po.nboff == 31);
assert(po.nbits == 8 * sizeof(po.tmpspace) - 24);
assert(po.buffer == po.tmpspace + 3);
assert(po.tmpspace[0] == 0x6F);
assert(po.tmpspace[1] == 0xf0);
assert(po.tmpspace[2] == 0xfe);
assert(po.tmpspace[3] == 0xff);
assert(po.tmpspace[4] == 0xff);
assert(po.tmpspace[5] == 0xff);
assert(po.tmpspace[6] == 0xfe);
}
int
main() {
check_per_decoding();
check_per_encoding();
return 0;
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment