aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLev Walkin <vlm@lionet.info>2004-06-06 07:20:02 +0000
committerLev Walkin <vlm@lionet.info>2004-06-06 07:20:02 +0000
commit4c36e308bbc8e4132a67ecc184e56afed183cb58 (patch)
tree044299c80b700ee7f4d1a07fbd5bc40a45f9393f
parent409c44e09f99a273fdab1381083133bdc1812df0 (diff)
tag2member
-rw-r--r--skeletons/ber_decoder.c2
-rw-r--r--skeletons/constr_CHOICE.c8
-rw-r--r--skeletons/constr_CHOICE.h10
-rw-r--r--skeletons/constr_SEQUENCE.c74
-rw-r--r--skeletons/constr_SEQUENCE.h9
-rw-r--r--skeletons/constr_SET.c10
-rw-r--r--skeletons/constr_SET.h13
-rw-r--r--skeletons/constr_SET_OF.h3
-rw-r--r--skeletons/constr_TYPE.h10
9 files changed, 103 insertions, 36 deletions
diff --git a/skeletons/ber_decoder.c b/skeletons/ber_decoder.c
index ab8d671c..09211edc 100644
--- a/skeletons/ber_decoder.c
+++ b/skeletons/ber_decoder.c
@@ -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?
- * Imagine two types,
+ * Imagine the two types,
* A ::= [5] IMPLICIT T
* B ::= [2] EXPLICIT T
* Where T is defined as
diff --git a/skeletons/constr_CHOICE.c b/skeletons/constr_CHOICE.c
index 1ecbbce7..d1beff42 100644
--- a/skeletons/constr_CHOICE.c
+++ b/skeletons/constr_CHOICE.c
@@ -67,8 +67,8 @@ static inline void _set_present_idx(void *sptr, int offset, int size, int pres);
*/
static int
_search4tag(const void *ap, const void *bp) {
- const asn1_CHOICE_tag2member_t *a = ap;
- const asn1_CHOICE_tag2member_t *b = 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);
@@ -180,8 +180,8 @@ CHOICE_decode_ber(asn1_TYPE_descriptor_t *sd,
}
do {
- asn1_CHOICE_tag2member_t *t2m;
- asn1_CHOICE_tag2member_t key;
+ asn1_TYPE_tag2member_t *t2m;
+ asn1_TYPE_tag2member_t key;
key.el_tag = tlv_tag;
t2m = bsearch(&key, specs->tag2el, specs->tag2el_count,
diff --git a/skeletons/constr_CHOICE.h b/skeletons/constr_CHOICE.h
index 70766e9d..1308bd4a 100644
--- a/skeletons/constr_CHOICE.h
+++ b/skeletons/constr_CHOICE.h
@@ -15,16 +15,10 @@ typedef struct asn1_CHOICE_element_s {
int optional; /* Whether the element is optional */
ber_tlv_tag_t tag; /* Outmost (most immediate) tag */
int tag_mode; /* IMPLICIT/no/EXPLICIT tag at current level */
- asn1_TYPE_descriptor_t
- *type; /* Member type descriptor */
+ asn1_TYPE_descriptor_t *type; /* Member type descriptor */
char *name; /* ASN.1 identifier of the element */
} 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 {
/*
* Target structure description.
@@ -43,7 +37,7 @@ typedef struct asn1_CHOICE_specifics_s {
/*
* Tags to members mapping table.
*/
- asn1_CHOICE_tag2member_t *tag2el;
+ asn1_TYPE_tag2member_t *tag2el;
int tag2el_count;
/*
diff --git a/skeletons/constr_SEQUENCE.c b/skeletons/constr_SEQUENCE.c
index 71689674..5c47df09 100644
--- a/skeletons/constr_SEQUENCE.c
+++ b/skeletons/constr_SEQUENCE.c
@@ -3,6 +3,7 @@
* Redistribution and modifications are permitted subject to BSD license.
*/
#include <constr_SEQUENCE.h>
+#include <assert.h>
/*
* Number of bytes left for this structure.
@@ -62,6 +63,35 @@
( ((memb_idx) > (specs)->ext_after) \
&&((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.
*/
@@ -151,6 +181,7 @@ SEQUENCE_decode_ber(asn1_TYPE_descriptor_t *sd,
void *memb_ptr2; /* Pointer to that pointer */
ssize_t tag_len; /* Length of TLV's T */
int opt_edx_end; /* Next non-optional element */
+ int use_bsearch;
int n;
if(ctx->step & 1)
@@ -196,9 +227,15 @@ SEQUENCE_decode_ber(asn1_TYPE_descriptor_t *sd,
/*
* Find the next available type with this tag.
*/
+ use_bsearch = 0;
opt_edx_end = edx + elements[edx].optional + 1;
if(opt_edx_end > specs->elements_count)
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++) {
if(BER_TAGS_EQUAL(tlv_tag, elements[n].tag)) {
/*
@@ -207,10 +244,39 @@ SEQUENCE_decode_ber(asn1_TYPE_descriptor_t *sd,
* Reposition over the right element.
*/
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;
}
}
+ 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 tag is unknown, it may be either
@@ -222,8 +288,9 @@ SEQUENCE_decode_ber(asn1_TYPE_descriptor_t *sd,
if(!IN_EXTENSION_GROUP(specs, edx)) {
ASN_DEBUG("Unexpected tag %s",
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),
+ elements[edx].name,
elements[edx].optional
?" or alternatives":"");
RETURN(RC_FAIL);
@@ -389,6 +456,7 @@ SEQUENCE_decode_ber(asn1_TYPE_descriptor_t *sd,
RETURN(RC_OK);
}
+
/*
* The DER encoder of the SEQUENCE type.
*/
@@ -574,7 +642,7 @@ SEQUENCE_constraint(asn1_TYPE_descriptor_t *td, const void *sptr,
const void *memb_ptr;
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;
} else {
memb_ptr = (const void *)((const char *)sptr + elm->memb_offset);
diff --git a/skeletons/constr_SEQUENCE.h b/skeletons/constr_SEQUENCE.h
index c15729ca..17754bb5 100644
--- a/skeletons/constr_SEQUENCE.h
+++ b/skeletons/constr_SEQUENCE.h
@@ -15,8 +15,7 @@ typedef struct asn1_SEQUENCE_element_s {
int optional; /* Whether the element is optional */
ber_tlv_tag_t tag; /* Outmost (most immediate) tag */
int tag_mode; /* IMPLICIT/no/EXPLICIT tag at current level */
- asn1_TYPE_descriptor_t
- *type; /* Member type descriptor */
+ asn1_TYPE_descriptor_t *type; /* Member type descriptor */
char *name; /* ASN.1 identifier of the element */
} asn1_SEQUENCE_element_t;
@@ -34,6 +33,12 @@ typedef struct asn1_SEQUENCE_specifics_s {
int elements_count;
/*
+ * Tags to members mapping table (sorted).
+ */
+ asn1_TYPE_tag2member_t *tag2el;
+ int tag2el_count;
+
+ /*
* Description of an extensions group.
*/
int ext_after; /* Extensions start after this member */
diff --git a/skeletons/constr_SET.c b/skeletons/constr_SET.c
index d0cac1d0..0385722c 100644
--- a/skeletons/constr_SET.c
+++ b/skeletons/constr_SET.c
@@ -61,8 +61,8 @@
*/
static int
_t2e_cmp(const void *ap, const void *bp) {
- const asn1_SET_tag2member_t *a = ap;
- const asn1_SET_tag2member_t *b = 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);
@@ -225,8 +225,8 @@ SET_decode_ber(asn1_TYPE_descriptor_t *sd,
* but is not strongly anticipated either.
*/
} else {
- asn1_SET_tag2member_t *t2m;
- asn1_SET_tag2member_t key;
+ asn1_TYPE_tag2member_t *t2m;
+ asn1_TYPE_tag2member_t key;
key.el_tag = tlv_tag;
t2m = bsearch(&key, specs->tag2el, specs->tag2el_count,
@@ -430,7 +430,7 @@ SET_encode_der(asn1_TYPE_descriptor_t *sd,
size_t computed_size = 0;
der_enc_rval_t my_erval;
int t2m_build_own = (specs->tag2el_count != specs->elements_count);
- asn1_SET_tag2member_t *t2m;
+ asn1_TYPE_tag2member_t *t2m;
int t2m_count;
ssize_t ret;
int edx;
diff --git a/skeletons/constr_SET.h b/skeletons/constr_SET.h
index c0ac07f5..8cb3fa8d 100644
--- a/skeletons/constr_SET.h
+++ b/skeletons/constr_SET.h
@@ -15,19 +15,10 @@ typedef struct asn1_SET_element_s {
int optional; /* Whether the element is optional */
ber_tlv_tag_t tag; /* Outmost (most immediate) tag */
int tag_mode; /* IMPLICIT/no/EXPLICIT tag at current level */
- asn1_TYPE_descriptor_t
- *type; /* Member type descriptor */
+ asn1_TYPE_descriptor_t *type; /* Member type descriptor */
char *name; /* ASN.1 identifier of the element */
} 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 {
/*
@@ -46,7 +37,7 @@ typedef struct asn1_SET_specifics_s {
/*
* Tags to members mapping table (sorted).
*/
- asn1_SET_tag2member_t *tag2el;
+ asn1_TYPE_tag2member_t *tag2el;
int tag2el_count;
/*
diff --git a/skeletons/constr_SET_OF.h b/skeletons/constr_SET_OF.h
index 814774dc..e2c6d8fd 100644
--- a/skeletons/constr_SET_OF.h
+++ b/skeletons/constr_SET_OF.h
@@ -9,8 +9,7 @@
typedef struct asn1_SET_OF_element_s {
ber_tlv_tag_t tag; /* Outmost (most immediate) tag */
- asn1_TYPE_descriptor_t
- *type; /* Member type descriptor */
+ asn1_TYPE_descriptor_t *type; /* Member type descriptor */
} asn1_SET_OF_element_t;
typedef struct asn1_SET_OF_specifics_s {
diff --git a/skeletons/constr_TYPE.h b/skeletons/constr_TYPE.h
index c7cfb22b..5c001049 100644
--- a/skeletons/constr_TYPE.h
+++ b/skeletons/constr_TYPE.h
@@ -84,6 +84,16 @@ typedef struct asn1_TYPE_descriptor_s {
} 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
* the contents of the target language's structure (struct_ptr) into the
* file pointer (stream) in human readable form.