Commit 0a8aa604 authored by Lev Walkin's avatar Lev Walkin

per encoding support

parent 5a621d6a
......@@ -571,7 +571,7 @@ INTEGER_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
if(ct && ct->flags & APC_EXTENSIBLE) {
int inext = per_get_few_bits(pd, 1);
if(inext < 0) _ASN_DECODE_FAILED;
if(inext < 0) _ASN_DECODE_STARVED;
if(inext) ct = 0;
}
......@@ -599,7 +599,7 @@ INTEGER_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
ASN_DEBUG("Integer with range %d bits", ct->range_bits);
if(ct->range_bits >= 0) {
long value = per_get_few_bits(pd, ct->range_bits);
if(value < 0) _ASN_DECODE_FAILED;
if(value < 0) _ASN_DECODE_STARVED;
ASN_DEBUG("Got value %ld + low %ld",
value, ct->lower_bound);
value += ct->lower_bound;
......@@ -619,14 +619,14 @@ INTEGER_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
/* Get the PER length */
len = uper_get_length(pd, -1, &repeat);
if(len < 0) _ASN_DECODE_FAILED;
if(len < 0) _ASN_DECODE_STARVED;
p = REALLOC(st->buf, st->size + len + 1);
if(!p) _ASN_DECODE_FAILED;
st->buf = (uint8_t *)p;
ret = per_get_many_bits(pd, &st->buf[st->size], 0, 8 * len);
if(ret < 0) _ASN_DECODE_FAILED;
if(ret < 0) _ASN_DECODE_STARVED;
st->size += len;
} while(repeat);
st->buf[st->size] = 0; /* JIC */
......
......@@ -96,13 +96,13 @@ NativeEnumerated_decode_uper(asn_codec_ctx_t *opt_codec_ctx,
if(ct->flags & APC_EXTENSIBLE) {
int inext = per_get_few_bits(pd, 1);
if(inext < 0) _ASN_DECODE_FAILED;
if(inext < 0) _ASN_DECODE_STARVED;
if(inext) ct = 0;
}
if(ct && ct->range_bits >= 0) {
value = per_get_few_bits(pd, ct->range_bits);
if(value < 0) _ASN_DECODE_FAILED;
if(value < 0) _ASN_DECODE_STARVED;
if(value >= (specs->extension
? specs->extension - 1 : specs->map_count))
_ASN_DECODE_FAILED;
......@@ -113,7 +113,7 @@ NativeEnumerated_decode_uper(asn_codec_ctx_t *opt_codec_ctx,
* X.691, #10.6: normally small non-negative whole number;
*/
value = uper_get_nsnnwn(pd);
if(value < 0) _ASN_DECODE_FAILED;
if(value < 0) _ASN_DECODE_STARVED;
value += specs->extension - 1;
if(value >= specs->map_count)
_ASN_DECODE_FAILED;
......
/*-
* 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.
*/
......@@ -1231,7 +1231,7 @@ OCTET_STRING_decode_uper(asn_codec_ctx_t *opt_codec_ctx,
if(ct->flags & APC_EXTENSIBLE) {
int inext = per_get_few_bits(pd, 1);
if(inext < 0) RETURN(RC_FAIL);
if(inext < 0) RETURN(RC_WMORE);
if(inext) ct = &asn_DEF_OCTET_STRING_constraint;
consumed_myself = 0;
}
......@@ -1254,7 +1254,7 @@ OCTET_STRING_decode_uper(asn_codec_ctx_t *opt_codec_ctx,
if(ct->effective_bits == 0) {
int ret = per_get_many_bits(pd, st->buf, 0,
unit_bits * ct->upper_bound);
if(ret < 0) RETURN(RC_FAIL);
if(ret < 0) RETURN(RC_WMORE);
consumed_myself += unit_bits * ct->upper_bound;
st->buf[st->size] = 0;
if(unit_bits == 1 && (ct->upper_bound & 0x7))
......@@ -1271,11 +1271,12 @@ OCTET_STRING_decode_uper(asn_codec_ctx_t *opt_codec_ctx,
/* Get the PER length */
len_bits = uper_get_length(pd, ct->effective_bits, &repeat);
if(len_bits < 0) RETURN(RC_FAIL);
if(len_bits < 0) RETURN(RC_WMORE);
len_bits += ct->lower_bound;
ASN_DEBUG("Got per length eb %ld, len %ld",
(long)ct->effective_bits, (long)len_bits);
ASN_DEBUG("Got PER length eb %ld, len %ld, %s (%s)",
(long)ct->effective_bits, (long)len_bits,
repeat ? "repeat" : "once", td->name);
if(unit_bits == 1) {
len_bytes = (len_bits + 7) >> 3;
if(len_bits & 0x7)
......@@ -1290,7 +1291,7 @@ OCTET_STRING_decode_uper(asn_codec_ctx_t *opt_codec_ctx,
st->buf = (uint8_t *)p;
ret = per_get_many_bits(pd, &st->buf[st->size], 0, len_bits);
if(ret < 0) RETURN(RC_FAIL);
if(ret < 0) RETURN(RC_WMORE);
st->size += len_bytes;
} while(repeat);
st->buf[st->size] = 0; /* nul-terminate */
......@@ -1327,8 +1328,8 @@ OCTET_STRING_encode_uper(asn_TYPE_descriptor_t *td,
sizeinunits = sizeinunits * 8 - (st->bits_unused & 0x07);
}
ASN_DEBUG("Encoding %s into %d units",
td->name, sizeinunits);
ASN_DEBUG("Encoding %s into %d units of %d bits",
td->name, sizeinunits, unit_bits);
/* Figure out wheter size lies within PER visible consrtaint */
......@@ -1361,7 +1362,7 @@ OCTET_STRING_encode_uper(asn_TYPE_descriptor_t *td,
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);
ret = per_put_many_bits(po, st->buf, sizeinunits * unit_bits);
if(ret) _ASN_ENCODE_FAILED;
_ASN_ENCODED_OK(er);
}
......@@ -1381,7 +1382,7 @@ OCTET_STRING_encode_uper(asn_TYPE_descriptor_t *td,
ASN_DEBUG("Encoding %d of %d", maySave, sizeinunits);
ret = per_put_many_bits(po, buf, maySave);
ret = per_put_many_bits(po, buf, maySave * unit_bits);
if(ret) _ASN_ENCODE_FAILED;
if(unit_bits == 1)
......
......@@ -93,6 +93,12 @@ typedef struct asn_dec_rval_s {
tmp_error.consumed = 0; \
return tmp_error; \
} while(0)
#define _ASN_DECODE_STARVED do { \
asn_dec_rval_t tmp_error; \
tmp_error.code = RC_WMORE; \
tmp_error.consumed = 0; \
return tmp_error; \
} while(0)
#ifdef __cplusplus
}
......
......@@ -852,22 +852,22 @@ CHOICE_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
if(ct && ct->flags & APC_EXTENSIBLE) {
value = per_get_few_bits(pd, 1);
if(value < 0) _ASN_DECODE_FAILED;
if(value < 0) _ASN_DECODE_STARVED;
if(value) ct = 0; /* Not restricted */
}
if(ct && ct->range_bits >= 0) {
value = per_get_few_bits(pd, ct->range_bits);
if(value < 0) _ASN_DECODE_FAILED;
if(value > ct->upper_bound)
_ASN_DECODE_FAILED;
if(value < 0) _ASN_DECODE_STARVED;
ASN_DEBUG("CHOICE %s got index %d in range %d",
td->name, value, ct->range_bits);
if(value > ct->upper_bound)
_ASN_DECODE_FAILED;
} else {
if(specs->ext_start == -1)
_ASN_DECODE_FAILED;
value = uper_get_nsnnwn(pd);
if(value < 0) _ASN_DECODE_FAILED;
if(value < 0) _ASN_DECODE_STARVED;
value += specs->ext_start;
if(value >= td->elements_count)
_ASN_DECODE_FAILED;
......
......@@ -1048,7 +1048,7 @@ SEQUENCE_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
/* Handle extensions */
if(specs->ext_before >= 0) {
extpresent = per_get_few_bits(pd, 1);
if(extpresent < 0) _ASN_DECODE_FAILED;
if(extpresent < 0) _ASN_DECODE_STARVED;
}
/* Prepare a place and read-in the presence bitmap */
......@@ -1058,7 +1058,7 @@ SEQUENCE_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
/* Get the presence map */
if(per_get_many_bits(pd, opres, 0, specs->roms_count)) {
FREEMEM(opres);
_ASN_DECODE_FAILED;
_ASN_DECODE_STARVED;
}
opmd.buffer = opres;
opmd.nboff = 0;
......
......@@ -883,7 +883,7 @@ SET_OF_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
if(ct && ct->flags & APC_EXTENSIBLE) {
int value = per_get_few_bits(pd, 1);
if(value < 0) _ASN_DECODE_FAILED;
if(value < 0) _ASN_DECODE_STARVED;
if(value) ct = 0; /* Not restricted! */
}
......@@ -892,7 +892,7 @@ SET_OF_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
nelems = per_get_few_bits(pd, ct->effective_bits);
ASN_DEBUG("Preparing to fetch %ld+%ld elements from %s",
(long)nelems, ct->lower_bound, td->name);
if(nelems < 0) _ASN_DECODE_FAILED;
if(nelems < 0) _ASN_DECODE_STARVED;
nelems += ct->lower_bound;
} else {
nelems = -1;
......@@ -905,7 +905,7 @@ SET_OF_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
ct ? ct->effective_bits : -1, &repeat);
ASN_DEBUG("Got to decode %d elements (eff %d)",
(int)nelems, (int)ct ? ct->effective_bits : -1);
if(nelems < 0) _ASN_DECODE_FAILED;
if(nelems < 0) _ASN_DECODE_STARVED;
}
for(i = 0; i < nelems; i++) {
......@@ -921,12 +921,13 @@ SET_OF_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
ASN_DEBUG("Failed to add element into %s",
td->name);
/* Fall through */
rv.code == RC_FAIL;
} else {
ASN_DEBUG("Failed decoding %s of %s (SET OF)",
elm->type->name, td->name);
}
if(ptr) ASN_STRUCT_FREE(*elm->type, ptr);
_ASN_DECODE_FAILED;
return rv;
}
nelems = -1; /* Allow uper_get_length() */
......
......@@ -3,12 +3,14 @@
#include <per_decoder.h>
asn_dec_rval_t
uper_decode(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, void **sptr, const void *buffer, size_t size, int skip_bits) {
uper_decode(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, void **sptr, const void *buffer, size_t size, int skip_bits, int unused_bits) {
asn_codec_ctx_t s_codec_ctx;
asn_dec_rval_t rval;
asn_per_data_t pd;
if(skip_bits < 0 || skip_bits > 7 || (skip_bits > 0 && !size))
if(skip_bits < 0 || skip_bits > 7
|| unused_bits < 0 || unused_bits > 7
|| (unused_bits > 0 && !size))
_ASN_DECODE_FAILED;
/*
......@@ -30,7 +32,9 @@ uper_decode(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, void **sp
/* Fill in the position indicator */
pd.buffer = (const uint8_t *)buffer;
pd.nboff = skip_bits;
pd.nbits = 8 * size; /* 8 is CHAR_BIT from <limits.h> */
pd.nbits = 8 * size - unused_bits; /* 8 is CHAR_BIT from <limits.h> */
if(pd.nboff > pd.nbits)
_ASN_DECODE_FAILED;
/*
* Invoke type-specific decoder.
......@@ -38,12 +42,13 @@ uper_decode(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, void **sp
if(!td->uper_decoder)
_ASN_DECODE_FAILED; /* PER is not compiled in */
rval = td->uper_decoder(opt_codec_ctx, td, 0, sptr, &pd);
if(rval.code == RC_FAIL) {
rval.consumed = 0;
} else {
if(rval.code == RC_OK) {
/* Return the number of consumed bits */
rval.consumed = ((pd.buffer - (const uint8_t *)buffer) << 3)
+ pd.nboff - skip_bits;
} else {
/* PER codec is not a restartable */
rval.consumed = 0;
}
return rval;
}
......
......@@ -22,7 +22,8 @@ asn_dec_rval_t uper_decode(struct asn_codec_ctx_s *opt_codec_ctx,
void **struct_ptr, /* Pointer to a target structure's pointer */
const void *buffer, /* Data to be decoded */
size_t size, /* Size of data buffer */
int skip_bits /* Number of unused leading bits, 0..7 */
int skip_bits, /* Number of unused leading bits, 0..7 */
int unused_bits /* Number of unused tailing bits, 0..7 */
);
......
......@@ -18,6 +18,9 @@ per_get_few_bits(asn_per_data_t *pd, int nbits) {
if(nbits < 0 || pd->nboff + nbits > pd->nbits)
return -1;
ASN_DEBUG("[PER get %d bits from %p+%d bits]",
nbits, pd->buffer, pd->nboff);
/*
* Normalize position indicator.
*/
......@@ -190,6 +193,9 @@ per_put_few_bits(asn_per_outp_t *po, uint32_t bits, int obits) {
if(obits <= 0 || obits >= 32) return obits ? -1 : 0;
ASN_DEBUG("[PER put %d bits to %p+%d bits]",
obits, po->buffer, po->nboff);
/*
* Normalize position indicator.
*/
......
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