Commit 4c36e308 authored by Lev Walkin's avatar Lev Walkin

tag2member

parent 409c44e0
...@@ -54,7 +54,7 @@ ber_check_tags(asn1_TYPE_descriptor_t *head, ber_dec_ctx_t *ctx, ...@@ -54,7 +54,7 @@ ber_check_tags(asn1_TYPE_descriptor_t *head, ber_dec_ctx_t *ctx,
/* /*
* So what does all this tags_impl_skip stuff mean? * So what does all this tags_impl_skip stuff mean?
* Imagine two types, * Imagine the two types,
* A ::= [5] IMPLICIT T * A ::= [5] IMPLICIT T
* B ::= [2] EXPLICIT T * B ::= [2] EXPLICIT T
* Where T is defined as * Where T is defined as
......
...@@ -67,8 +67,8 @@ static inline void _set_present_idx(void *sptr, int offset, int size, int pres); ...@@ -67,8 +67,8 @@ static inline void _set_present_idx(void *sptr, int offset, int size, int pres);
*/ */
static int static int
_search4tag(const void *ap, const void *bp) { _search4tag(const void *ap, const void *bp) {
const asn1_CHOICE_tag2member_t *a = ap; const asn1_TYPE_tag2member_t *a = ap;
const asn1_CHOICE_tag2member_t *b = bp; const asn1_TYPE_tag2member_t *b = bp;
int a_class = BER_TAG_CLASS(a->el_tag); int a_class = BER_TAG_CLASS(a->el_tag);
int b_class = BER_TAG_CLASS(b->el_tag); int b_class = BER_TAG_CLASS(b->el_tag);
...@@ -180,8 +180,8 @@ CHOICE_decode_ber(asn1_TYPE_descriptor_t *sd, ...@@ -180,8 +180,8 @@ CHOICE_decode_ber(asn1_TYPE_descriptor_t *sd,
} }
do { do {
asn1_CHOICE_tag2member_t *t2m; asn1_TYPE_tag2member_t *t2m;
asn1_CHOICE_tag2member_t key; asn1_TYPE_tag2member_t key;
key.el_tag = tlv_tag; key.el_tag = tlv_tag;
t2m = bsearch(&key, specs->tag2el, specs->tag2el_count, t2m = bsearch(&key, specs->tag2el, specs->tag2el_count,
......
...@@ -15,16 +15,10 @@ typedef struct asn1_CHOICE_element_s { ...@@ -15,16 +15,10 @@ typedef struct asn1_CHOICE_element_s {
int optional; /* Whether the element is optional */ int optional; /* Whether the element is optional */
ber_tlv_tag_t tag; /* Outmost (most immediate) tag */ ber_tlv_tag_t tag; /* Outmost (most immediate) tag */
int tag_mode; /* IMPLICIT/no/EXPLICIT tag at current level */ int tag_mode; /* IMPLICIT/no/EXPLICIT tag at current level */
asn1_TYPE_descriptor_t asn1_TYPE_descriptor_t *type; /* Member type descriptor */
*type; /* Member type descriptor */
char *name; /* ASN.1 identifier of the element */ char *name; /* ASN.1 identifier of the element */
} asn1_CHOICE_element_t; } asn1_CHOICE_element_t;
typedef struct asn1_CHOICE_tag2member_s {
ber_tlv_tag_t el_tag; /* Outmost tag of the member */
int el_no; /* Index of the associated member, base 0 */
} asn1_CHOICE_tag2member_t;
typedef struct asn1_CHOICE_specifics_s { typedef struct asn1_CHOICE_specifics_s {
/* /*
* Target structure description. * Target structure description.
...@@ -43,7 +37,7 @@ typedef struct asn1_CHOICE_specifics_s { ...@@ -43,7 +37,7 @@ typedef struct asn1_CHOICE_specifics_s {
/* /*
* Tags to members mapping table. * Tags to members mapping table.
*/ */
asn1_CHOICE_tag2member_t *tag2el; asn1_TYPE_tag2member_t *tag2el;
int tag2el_count; int tag2el_count;
/* /*
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
* Redistribution and modifications are permitted subject to BSD license. * Redistribution and modifications are permitted subject to BSD license.
*/ */
#include <constr_SEQUENCE.h> #include <constr_SEQUENCE.h>
#include <assert.h>
/* /*
* Number of bytes left for this structure. * Number of bytes left for this structure.
...@@ -62,6 +63,35 @@ ...@@ -62,6 +63,35 @@
( ((memb_idx) > (specs)->ext_after) \ ( ((memb_idx) > (specs)->ext_after) \
&&((memb_idx) < (specs)->ext_before)) &&((memb_idx) < (specs)->ext_before))
/*
* Tags are canonically sorted in the tag2element map.
*/
static int
_t2e_cmp(const void *ap, const void *bp) {
const asn1_TYPE_tag2member_t *a = ap;
const asn1_TYPE_tag2member_t *b = bp;
int a_class = BER_TAG_CLASS(a->el_tag);
int b_class = BER_TAG_CLASS(b->el_tag);
if(a_class == b_class) {
ber_tlv_tag_t a_value = BER_TAG_VALUE(a->el_tag);
ber_tlv_tag_t b_value = BER_TAG_VALUE(b->el_tag);
if(a_value == b_value)
return 0;
else if(a_value < b_value)
return -1;
else
return 1;
} else if(a_class < b_class) {
return -1;
} else {
return 1;
}
}
/* /*
* The decoder of the SEQUENCE type. * The decoder of the SEQUENCE type.
*/ */
...@@ -151,6 +181,7 @@ SEQUENCE_decode_ber(asn1_TYPE_descriptor_t *sd, ...@@ -151,6 +181,7 @@ SEQUENCE_decode_ber(asn1_TYPE_descriptor_t *sd,
void *memb_ptr2; /* Pointer to that pointer */ void *memb_ptr2; /* Pointer to that pointer */
ssize_t tag_len; /* Length of TLV's T */ ssize_t tag_len; /* Length of TLV's T */
int opt_edx_end; /* Next non-optional element */ int opt_edx_end; /* Next non-optional element */
int use_bsearch;
int n; int n;
if(ctx->step & 1) if(ctx->step & 1)
...@@ -196,9 +227,15 @@ SEQUENCE_decode_ber(asn1_TYPE_descriptor_t *sd, ...@@ -196,9 +227,15 @@ SEQUENCE_decode_ber(asn1_TYPE_descriptor_t *sd,
/* /*
* Find the next available type with this tag. * Find the next available type with this tag.
*/ */
use_bsearch = 0;
opt_edx_end = edx + elements[edx].optional + 1; opt_edx_end = edx + elements[edx].optional + 1;
if(opt_edx_end > specs->elements_count) if(opt_edx_end > specs->elements_count)
opt_edx_end = specs->elements_count; /* Cap */ opt_edx_end = specs->elements_count; /* Cap */
else if(opt_edx_end - edx > 5) {
/* Limit the scope of linear search */
opt_edx_end = edx + 5;
use_bsearch = 1;
}
for(n = edx; n < opt_edx_end; n++) { for(n = edx; n < opt_edx_end; n++) {
if(BER_TAGS_EQUAL(tlv_tag, elements[n].tag)) { if(BER_TAGS_EQUAL(tlv_tag, elements[n].tag)) {
/* /*
...@@ -207,10 +244,39 @@ SEQUENCE_decode_ber(asn1_TYPE_descriptor_t *sd, ...@@ -207,10 +244,39 @@ SEQUENCE_decode_ber(asn1_TYPE_descriptor_t *sd,
* Reposition over the right element. * Reposition over the right element.
*/ */
edx = n; edx = n;
ctx->step = 2 * edx; /* Remember! */ ctx->step = 1 + 2 * edx; /* Remember! */
goto microphase2;
} else if(elements[n].tag == (ber_tlv_tag_t)-1) {
use_bsearch = 1;
break; break;
} }
} }
if(use_bsearch) {
/*
* Resorch to a binary search over
* sorted array of tags.
*/
asn1_TYPE_tag2member_t *t2m;
asn1_TYPE_tag2member_t key;
key.el_tag = tlv_tag;
t2m = bsearch(&key, specs->tag2el, specs->tag2el_count,
sizeof(specs->tag2el[0]), _t2e_cmp);
if(t2m && t2m->el_no >= edx) {
/*
* Rewind to the first element with that tag,
* `cause bsearch() does not guarantee order.
*/
while(t2m > specs->tag2el
&& BER_TAGS_EQUAL(tlv_tag,
t2m[-1].el_tag)
&& t2m[-1].el_no >= edx)
t2m++;
edx = t2m->el_no;
ctx->step = 1 + 2 * edx;
goto microphase2;
}
n = opt_edx_end;
}
if(n == opt_edx_end) { if(n == opt_edx_end) {
/* /*
* If tag is unknown, it may be either * If tag is unknown, it may be either
...@@ -222,8 +288,9 @@ SEQUENCE_decode_ber(asn1_TYPE_descriptor_t *sd, ...@@ -222,8 +288,9 @@ SEQUENCE_decode_ber(asn1_TYPE_descriptor_t *sd,
if(!IN_EXTENSION_GROUP(specs, edx)) { if(!IN_EXTENSION_GROUP(specs, edx)) {
ASN_DEBUG("Unexpected tag %s", ASN_DEBUG("Unexpected tag %s",
ber_tlv_tag_string(tlv_tag)); ber_tlv_tag_string(tlv_tag));
ASN_DEBUG("Expected tag %s%s", ASN_DEBUG("Expected tag %s (%s)%s",
ber_tlv_tag_string(elements[edx].tag), ber_tlv_tag_string(elements[edx].tag),
elements[edx].name,
elements[edx].optional elements[edx].optional
?" or alternatives":""); ?" or alternatives":"");
RETURN(RC_FAIL); RETURN(RC_FAIL);
...@@ -389,6 +456,7 @@ SEQUENCE_decode_ber(asn1_TYPE_descriptor_t *sd, ...@@ -389,6 +456,7 @@ SEQUENCE_decode_ber(asn1_TYPE_descriptor_t *sd,
RETURN(RC_OK); RETURN(RC_OK);
} }
/* /*
* The DER encoder of the SEQUENCE type. * The DER encoder of the SEQUENCE type.
*/ */
...@@ -574,7 +642,7 @@ SEQUENCE_constraint(asn1_TYPE_descriptor_t *td, const void *sptr, ...@@ -574,7 +642,7 @@ SEQUENCE_constraint(asn1_TYPE_descriptor_t *td, const void *sptr,
const void *memb_ptr; const void *memb_ptr;
if(elm->optional) { if(elm->optional) {
memb_ptr = *(const void **)((const char *)sptr + elm->memb_offset); memb_ptr = *(const void * const *)((const char *)sptr + elm->memb_offset);
if(!memb_ptr) continue; if(!memb_ptr) continue;
} else { } else {
memb_ptr = (const void *)((const char *)sptr + elm->memb_offset); memb_ptr = (const void *)((const char *)sptr + elm->memb_offset);
......
...@@ -15,8 +15,7 @@ typedef struct asn1_SEQUENCE_element_s { ...@@ -15,8 +15,7 @@ typedef struct asn1_SEQUENCE_element_s {
int optional; /* Whether the element is optional */ int optional; /* Whether the element is optional */
ber_tlv_tag_t tag; /* Outmost (most immediate) tag */ ber_tlv_tag_t tag; /* Outmost (most immediate) tag */
int tag_mode; /* IMPLICIT/no/EXPLICIT tag at current level */ int tag_mode; /* IMPLICIT/no/EXPLICIT tag at current level */
asn1_TYPE_descriptor_t asn1_TYPE_descriptor_t *type; /* Member type descriptor */
*type; /* Member type descriptor */
char *name; /* ASN.1 identifier of the element */ char *name; /* ASN.1 identifier of the element */
} asn1_SEQUENCE_element_t; } asn1_SEQUENCE_element_t;
...@@ -33,6 +32,12 @@ typedef struct asn1_SEQUENCE_specifics_s { ...@@ -33,6 +32,12 @@ typedef struct asn1_SEQUENCE_specifics_s {
asn1_SEQUENCE_element_t *elements; asn1_SEQUENCE_element_t *elements;
int elements_count; int elements_count;
/*
* Tags to members mapping table (sorted).
*/
asn1_TYPE_tag2member_t *tag2el;
int tag2el_count;
/* /*
* Description of an extensions group. * Description of an extensions group.
*/ */
......
...@@ -61,8 +61,8 @@ ...@@ -61,8 +61,8 @@
*/ */
static int static int
_t2e_cmp(const void *ap, const void *bp) { _t2e_cmp(const void *ap, const void *bp) {
const asn1_SET_tag2member_t *a = ap; const asn1_TYPE_tag2member_t *a = ap;
const asn1_SET_tag2member_t *b = bp; const asn1_TYPE_tag2member_t *b = bp;
int a_class = BER_TAG_CLASS(a->el_tag); int a_class = BER_TAG_CLASS(a->el_tag);
int b_class = BER_TAG_CLASS(b->el_tag); int b_class = BER_TAG_CLASS(b->el_tag);
...@@ -225,8 +225,8 @@ SET_decode_ber(asn1_TYPE_descriptor_t *sd, ...@@ -225,8 +225,8 @@ SET_decode_ber(asn1_TYPE_descriptor_t *sd,
* but is not strongly anticipated either. * but is not strongly anticipated either.
*/ */
} else { } else {
asn1_SET_tag2member_t *t2m; asn1_TYPE_tag2member_t *t2m;
asn1_SET_tag2member_t key; asn1_TYPE_tag2member_t key;
key.el_tag = tlv_tag; key.el_tag = tlv_tag;
t2m = bsearch(&key, specs->tag2el, specs->tag2el_count, t2m = bsearch(&key, specs->tag2el, specs->tag2el_count,
...@@ -430,7 +430,7 @@ SET_encode_der(asn1_TYPE_descriptor_t *sd, ...@@ -430,7 +430,7 @@ SET_encode_der(asn1_TYPE_descriptor_t *sd,
size_t computed_size = 0; size_t computed_size = 0;
der_enc_rval_t my_erval; der_enc_rval_t my_erval;
int t2m_build_own = (specs->tag2el_count != specs->elements_count); int t2m_build_own = (specs->tag2el_count != specs->elements_count);
asn1_SET_tag2member_t *t2m; asn1_TYPE_tag2member_t *t2m;
int t2m_count; int t2m_count;
ssize_t ret; ssize_t ret;
int edx; int edx;
......
...@@ -15,19 +15,10 @@ typedef struct asn1_SET_element_s { ...@@ -15,19 +15,10 @@ typedef struct asn1_SET_element_s {
int optional; /* Whether the element is optional */ int optional; /* Whether the element is optional */
ber_tlv_tag_t tag; /* Outmost (most immediate) tag */ ber_tlv_tag_t tag; /* Outmost (most immediate) tag */
int tag_mode; /* IMPLICIT/no/EXPLICIT tag at current level */ int tag_mode; /* IMPLICIT/no/EXPLICIT tag at current level */
asn1_TYPE_descriptor_t asn1_TYPE_descriptor_t *type; /* Member type descriptor */
*type; /* Member type descriptor */
char *name; /* ASN.1 identifier of the element */ char *name; /* ASN.1 identifier of the element */
} asn1_SET_element_t; } asn1_SET_element_t;
/*
* Map between the outmost tag of the element and the corresponding
* element's index.
*/
typedef struct asn1_SET_tag2member_s {
ber_tlv_tag_t el_tag; /* Outmost tag of the member */
int el_no; /* Index of the associated member, base 0 */
} asn1_SET_tag2member_t;
typedef struct asn1_SET_specifics_s { typedef struct asn1_SET_specifics_s {
/* /*
...@@ -46,7 +37,7 @@ typedef struct asn1_SET_specifics_s { ...@@ -46,7 +37,7 @@ typedef struct asn1_SET_specifics_s {
/* /*
* Tags to members mapping table (sorted). * Tags to members mapping table (sorted).
*/ */
asn1_SET_tag2member_t *tag2el; asn1_TYPE_tag2member_t *tag2el;
int tag2el_count; int tag2el_count;
/* /*
......
...@@ -9,8 +9,7 @@ ...@@ -9,8 +9,7 @@
typedef struct asn1_SET_OF_element_s { typedef struct asn1_SET_OF_element_s {
ber_tlv_tag_t tag; /* Outmost (most immediate) tag */ ber_tlv_tag_t tag; /* Outmost (most immediate) tag */
asn1_TYPE_descriptor_t asn1_TYPE_descriptor_t *type; /* Member type descriptor */
*type; /* Member type descriptor */
} asn1_SET_OF_element_t; } asn1_SET_OF_element_t;
typedef struct asn1_SET_OF_specifics_s { typedef struct asn1_SET_OF_specifics_s {
......
...@@ -83,6 +83,16 @@ typedef struct asn1_TYPE_descriptor_s { ...@@ -83,6 +83,16 @@ typedef struct asn1_TYPE_descriptor_s {
void *specifics; void *specifics;
} asn1_TYPE_descriptor_t; } asn1_TYPE_descriptor_t;
/*
* BER tag to element number mapping.
*/
typedef struct asn1_TYPE_tag2member_s {
ber_tlv_tag_t el_tag; /* Outmost tag of the member */
int el_no; /* Index of the associated member, base 0 */
} asn1_TYPE_tag2member_t;
/* /*
* This function is a wrapper around (td)->print_struct, which prints out * This function is a wrapper around (td)->print_struct, which prints out
* the contents of the target language's structure (struct_ptr) into the * the contents of the target language's structure (struct_ptr) into the
......
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