better parsing information object class sets
diff --git a/libasn1parser/asn1p_class.c b/libasn1parser/asn1p_class.c
index 4603d18..666e0a2 100644
--- a/libasn1parser/asn1p_class.c
+++ b/libasn1parser/asn1p_class.c
@@ -62,6 +62,36 @@
}
}
+int
+asn1p_ioc_row_match(const asn1p_ioc_row_t *a, const asn1p_ioc_row_t *b) {
+ assert(a && b);
+
+ if(a->columns != b->columns)
+ return -1; /* Bad! */
+
+ for(size_t i = 0; i < a->columns; i++) {
+ assert(a->column[i].field);
+ assert(b->column[i].field);
+ if(strcmp(a->column[i].field->Identifier,
+ b->column[i].field->Identifier)
+ != 0) {
+ return -1; /* Bad! */
+ }
+ if((a->column[i].value && !b->column[i].value)
+ || (!a->column[i].value && b->column[i].value)) {
+ return 1; /* Not match */
+ }
+ if(a->column[i].value && b->column[i].value) {
+ if(asn1p_expr_compare(a->column[i].value, b->column[i].value)
+ != 0) {
+ return 1; /* Not match */
+ }
+ }
+ }
+
+ return 0;
+}
+
struct asn1p_ioc_cell_s *
asn1p_ioc_row_cell_fetch(asn1p_ioc_row_t *row, const char *fieldname) {
int i;
diff --git a/libasn1parser/asn1p_class.h b/libasn1parser/asn1p_class.h
index 893dec3..08fd374 100644
--- a/libasn1parser/asn1p_class.h
+++ b/libasn1parser/asn1p_class.h
@@ -20,6 +20,13 @@
asn1p_ioc_row_t *asn1p_ioc_row_new(struct asn1p_expr_s *oclass);
void asn1p_ioc_row_delete(asn1p_ioc_row_t *);
+
+/*
+ * Match is similar to a comparison,
+ * but -1 means error and 1 means not equal. 0 is OK
+ */
+int asn1p_ioc_row_match(const asn1p_ioc_row_t *, const asn1p_ioc_row_t *);
+
struct asn1p_ioc_cell_s *asn1p_ioc_row_cell_fetch(asn1p_ioc_row_t *,
const char *fieldname);
diff --git a/libasn1parser/asn1p_constr.c b/libasn1parser/asn1p_constr.c
index d471684..a9e939d 100644
--- a/libasn1parser/asn1p_constr.c
+++ b/libasn1parser/asn1p_constr.c
@@ -6,6 +6,28 @@
#include "asn1parser.h"
+void
+asn1p_constraint_set_source(asn1p_constraint_t *ct,
+ struct asn1p_module_s *module, int lineno) {
+ if(ct) {
+ ct->module = module;
+ ct->_lineno = lineno;
+ asn1p_value_set_source(ct->containedSubtype,module,lineno);
+ asn1p_value_set_source(ct->value,module,lineno);
+ asn1p_value_set_source(ct->range_start,module,lineno);
+ asn1p_value_set_source(ct->range_stop,module,lineno);
+ for(size_t i = 0; i < ct->el_count; i++) {
+ asn1p_constraint_set_source(ct->elements[i], module, lineno);
+ }
+ }
+}
+
+int asn1p_constraint_compare(const asn1p_constraint_t *a,
+ const asn1p_constraint_t *b) {
+ assert(!"Constraint comparison is not implemented");
+ return -1;
+}
+
asn1p_constraint_t *
asn1p_constraint_new(int _lineno, asn1p_module_t *mod) {
asn1p_constraint_t *ct;
@@ -189,3 +211,20 @@
}
return "UNKNOWN";
}
+
+const asn1p_constraint_t *
+asn1p_get_component_relation_constraint(asn1p_constraint_t *ct) {
+ if(ct) {
+ if(ct->type == ACT_CA_CRC)
+ return ct;
+ if(ct->type == ACT_CA_SET) {
+ for(size_t i = 0; i < ct->el_count; i++) {
+ const asn1p_constraint_t *tmp =
+ asn1p_get_component_relation_constraint(ct->elements[i]);
+ if(tmp) return tmp;
+ }
+ }
+ }
+ return NULL;
+}
+
diff --git a/libasn1parser/asn1p_constr.h b/libasn1parser/asn1p_constr.h
index 7edd63f..2351628 100644
--- a/libasn1parser/asn1p_constr.h
+++ b/libasn1parser/asn1p_constr.h
@@ -71,6 +71,14 @@
/* Human-readable constraint type description */
const char *asn1p_constraint_type2str(enum asn1p_constraint_type_e);
+const asn1p_constraint_t *asn1p_get_component_relation_constraint(
+ asn1p_constraint_t *);
+
+int asn1p_constraint_compare(const asn1p_constraint_t *,
+ const asn1p_constraint_t *);
+void asn1p_constraint_set_source(asn1p_constraint_t *,
+ struct asn1p_module_s *module, int lineno);
+
/*
* Constructors and a recursive destructor.
*/
diff --git a/libasn1parser/asn1p_expr.c b/libasn1parser/asn1p_expr.c
index 7a24d06..4383ea1 100644
--- a/libasn1parser/asn1p_expr.c
+++ b/libasn1parser/asn1p_expr.c
@@ -9,6 +9,82 @@
static asn1p_expr_t *asn1p_expr_clone_impl(asn1p_expr_t *expr, int skip_extensions, asn1p_expr_t *(*)(asn1p_expr_t *, void *), void *);
static asn1p_value_t *value_resolver(asn1p_value_t *, void *arg);
+void
+asn1p_expr_set_source(asn1p_expr_t *expr, asn1p_module_t *module, int lineno) {
+ if(expr) {
+ expr->module = module;
+ expr->_lineno = lineno;
+ asn1p_ref_set_source(expr->reference, module, lineno);
+ asn1p_value_set_source(expr->value, module, lineno);
+ asn1p_constraint_set_source(expr->constraints, module, lineno);
+ asn1p_constraint_set_source(expr->combined_constraints, module, lineno);
+ asn1p_expr_set_source(expr->rhs_pspecs, module, lineno);
+
+ asn1p_expr_t *memb;
+
+ TQ_FOR(memb, &(expr->members), next) {
+ asn1p_expr_set_source(memb, module, lineno);
+ }
+ }
+}
+
+int
+asn1p_expr_compare(const asn1p_expr_t *a, const asn1p_expr_t *b) {
+ if(a->meta_type != b->meta_type || a->expr_type != b->expr_type) {
+ return -1;
+ }
+
+ if((!a->Identifier && b->Identifier) || (a->Identifier && !b->Identifier)) {
+ return -1;
+ } else if(a->Identifier && strcmp(a->Identifier, b->Identifier)) {
+ return -1;
+ }
+
+ if((!a->reference && b->reference) || (a->reference && !b->reference)) {
+ return -1;
+ } else if(a->reference
+ && asn1p_ref_compare(a->reference, b->reference) != 0) {
+ return -1;
+ }
+
+ if((!a->value && b->value) || (a->value && !b->value)) {
+ return -1;
+ } else if(a->value && asn1p_value_compare(a->value, b->value)) {
+ return -1;
+ }
+
+ if((a->tag.tag_class != b->tag.tag_class)
+ || (a->tag.tag_mode != b->tag.tag_mode)
+ || (a->tag.tag_value != b->tag.tag_value)) {
+ return -1;
+ }
+
+ if((a->marker.flags != b->marker.flags)
+ || (a->marker.default_value && !b->marker.default_value)
+ || (!a->marker.default_value && b->marker.default_value)
+ || (a->marker.default_value
+ && asn1p_value_compare(a->marker.default_value,
+ b->marker.default_value))) {
+ return -1;
+ }
+
+ if(a->unique != b->unique) {
+ return -1;
+ }
+
+ const asn1p_expr_t *am = TQ_FIRST(&a->members);
+ const asn1p_expr_t *bm = TQ_FIRST(&b->members);
+ for(; am || bm; am = TQ_NEXT(am, next), bm = TQ_NEXT(bm, next)) {
+ if((am && !bm) || (!am && bm)) {
+ return -1;
+ } else if(asn1p_expr_compare(am, bm) != 0) {
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
/*
* Construct a new empty types collection.
*/
diff --git a/libasn1parser/asn1p_expr.h b/libasn1parser/asn1p_expr.h
index 6f2503b..524f532 100644
--- a/libasn1parser/asn1p_expr.h
+++ b/libasn1parser/asn1p_expr.h
@@ -281,7 +281,10 @@
void *resolver_arg);
void asn1p_expr_add(asn1p_expr_t *to, asn1p_expr_t *what);
void asn1p_expr_add_many(asn1p_expr_t *to, asn1p_expr_t *from_what);
+int asn1p_expr_compare(const asn1p_expr_t *, const asn1p_expr_t *);
void asn1p_expr_free(asn1p_expr_t *expr);
+void asn1p_expr_set_source(asn1p_expr_t *, asn1p_module_t *, int lineno);
+
#define TAG2STRING_BUFFER_SIZE 64 /* buf should be at least this big */
char *asn1p_tag2string(struct asn1p_type_tag_s *tag, char *opt_buf);
diff --git a/libasn1parser/asn1p_oid.c b/libasn1parser/asn1p_oid.c
index 14b96aa..a71c8c4 100644
--- a/libasn1parser/asn1p_oid.c
+++ b/libasn1parser/asn1p_oid.c
@@ -81,7 +81,7 @@
}
int
-asn1p_oid_compare(asn1p_oid_t *a, asn1p_oid_t *b) {
+asn1p_oid_compare(const asn1p_oid_t *a, const asn1p_oid_t *b) {
int i;
for(i = 0; ; i++) {
diff --git a/libasn1parser/asn1p_oid.h b/libasn1parser/asn1p_oid.h
index 489a3c5..1b7ba52 100644
--- a/libasn1parser/asn1p_oid.h
+++ b/libasn1parser/asn1p_oid.h
@@ -61,7 +61,7 @@
* 0: The specified OIDs are equal.
* -1 or 1 otherwise.
*/
-int asn1p_oid_compare(asn1p_oid_t *a, asn1p_oid_t *b);
+int asn1p_oid_compare(const asn1p_oid_t *a, const asn1p_oid_t *b);
#endif /* ASN1_PARSER_OID_H */
diff --git a/libasn1parser/asn1p_ref.c b/libasn1parser/asn1p_ref.c
index 3ea9b58..64f51b4 100644
--- a/libasn1parser/asn1p_ref.c
+++ b/libasn1parser/asn1p_ref.c
@@ -14,10 +14,8 @@
asn1p_ref_t *ref;
ref = calloc(1, sizeof *ref);
- if(ref) {
- ref->_lineno = _lineno;
- ref->module = mod;
- }
+ assert(ref);
+ asn1p_ref_set_source(ref, mod, _lineno);
return ref;
}
@@ -39,6 +37,14 @@
}
}
+void
+asn1p_ref_set_source(asn1p_ref_t *ref, asn1p_module_t *module, int lineno) {
+ if(ref) {
+ ref->module = module;
+ ref->_lineno = lineno;
+ }
+}
+
static enum asn1p_ref_lex_type_e
asn1p_ref_name2lextype(const char *name) {
enum asn1p_ref_lex_type_e lex_type;
@@ -136,3 +142,51 @@
return newref;
}
+
+int
+asn1p_ref_compare(const asn1p_ref_t *a, const asn1p_ref_t *b) {
+ if(a->comp_count != b->comp_count)
+ return -1;
+ if(a->module != b->module)
+ return -1;
+
+ for(size_t i = 0; i < a->comp_count; i++) {
+ if(a->components[i].lex_type != b->components[i].lex_type
+ || strcmp(a->components[i].name, b->components[i].name) != 0) {
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+const char *
+asn1p_ref_string(const asn1p_ref_t *ref) {
+ static char static_buf[32];
+ static char *buf = static_buf;
+ static size_t buf_size = sizeof(static_buf);
+ char *p = buf;
+
+ for(size_t i = 0; i < ref->comp_count; i++) {
+ size_t space = buf_size - (p - buf);
+ int ret =
+ snprintf(p, space, "%s%s", i ? "." : "", ref->components[i].name);
+ if(ret < 0 || (size_t)ret >= space) {
+ i--;
+ char *tmp = malloc(buf_size * 2 + 1);
+ assert(tmp);
+ size_t p_offset = p - buf;
+ memcpy(tmp, buf, (p - buf));
+ if(buf != static_buf) free(buf);
+ buf_size *= 2;
+ buf = tmp;
+ p = tmp + p_offset;
+ } else {
+ p += ret;
+ }
+ }
+
+ *p = '\0';
+ return buf;
+}
+
diff --git a/libasn1parser/asn1p_ref.h b/libasn1parser/asn1p_ref.h
index c4d8b5c..776289b 100644
--- a/libasn1parser/asn1p_ref.h
+++ b/libasn1parser/asn1p_ref.h
@@ -49,6 +49,20 @@
asn1p_ref_t *asn1p_ref_clone(asn1p_ref_t *ref);
+void asn1p_ref_set_source(asn1p_ref_t *, asn1p_module_t *module, int lineno);
+
+
+/*
+ * Lexicographically compare references.
+ */
+int asn1p_ref_compare(const asn1p_ref_t *, const asn1p_ref_t *);
+
+/*
+ * Return a pointer to a statically allocated buffer representing the
+ * complete reference.
+ */
+const char *asn1p_ref_string(const asn1p_ref_t *);
+
/*
* Add a new reference component to the existing reference structure.
*
diff --git a/libasn1parser/asn1p_value.c b/libasn1parser/asn1p_value.c
index fa3c1f4..9bd7563 100644
--- a/libasn1parser/asn1p_value.c
+++ b/libasn1parser/asn1p_value.c
@@ -4,7 +4,85 @@
#include <assert.h>
#include "asn1parser.h"
+#include "asn1p_expr.h"
+void
+asn1p_value_set_source(asn1p_value_t *value, asn1p_module_t *module,
+ int lineno) {
+ if(value) {
+ switch(value->type) {
+ case ATV_TYPE:
+ asn1p_expr_set_source(value->value.v_type, module, lineno);
+ break;
+ case ATV_REFERENCED:
+ asn1p_ref_set_source(value->value.reference, module, lineno);
+ break;
+ case ATV_VALUESET:
+ asn1p_constraint_set_source(value->value.constraint, module,
+ lineno);
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+int
+asn1p_value_compare(const asn1p_value_t *a, const asn1p_value_t *b) {
+ if(a->type != b->type) {
+ return -1;
+ }
+
+ switch(a->type) {
+ case ATV_NULL:
+ case ATV_NOVALUE:
+ case ATV_MAX:
+ case ATV_MIN:
+ case ATV_FALSE:
+ case ATV_TRUE:
+ break;
+ case ATV_TYPE:
+ return asn1p_expr_compare(a->value.v_type, b->value.v_type);
+ case ATV_REAL:
+ return (a->value.v_double == b->value.v_double) ? 0 : -1;
+ case ATV_INTEGER:
+ case ATV_TUPLE:
+ case ATV_QUADRUPLE:
+ return (a->value.v_integer == b->value.v_integer) ? 0 : -1;
+ case ATV_STRING:
+ case ATV_UNPARSED:
+ if(a->value.string.size != b->value.string.size
+ || memcmp(a->value.string.buf, b->value.string.buf,
+ a->value.string.size)
+ != 0) {
+ return -1;
+ }
+ return 0;
+ case ATV_BITVECTOR:
+ if(a->value.binary_vector.size_in_bits
+ != b->value.binary_vector.size_in_bits
+ || memcmp(a->value.binary_vector.bits, b->value.binary_vector.bits,
+ (a->value.binary_vector.size_in_bits+7) >> 3)
+ != 0) {
+ return -1;
+ }
+ case ATV_VALUESET:
+ return asn1p_constraint_compare(a->value.constraint,
+ b->value.constraint);
+ case ATV_REFERENCED:
+ return asn1p_ref_compare(a->value.reference, b->value.reference);
+ case ATV_CHOICE_IDENTIFIER:
+ if(strcmp(a->value.choice_identifier.identifier,
+ b->value.choice_identifier.identifier)
+ != 0) {
+ return -1;
+ }
+ return asn1p_value_compare(a->value.choice_identifier.value,
+ b->value.choice_identifier.value);
+ }
+
+ return 0;
+}
asn1p_value_t *
asn1p_value_fromref(asn1p_ref_t *ref, int do_copy) {
diff --git a/libasn1parser/asn1p_value.h b/libasn1parser/asn1p_value.h
index c260c27..c1167f3 100644
--- a/libasn1parser/asn1p_value.h
+++ b/libasn1parser/asn1p_value.h
@@ -5,6 +5,7 @@
#define ASN1_PARSER_VALUE_H
struct asn1p_constraint_s; /* Forward declaration */
+struct asn1p_module_s;
struct asn1p_expr_s;
/*
@@ -76,5 +77,7 @@
asn1p_value_t *asn1p_value_clone_with_resolver(asn1p_value_t *,
asn1p_value_t *(*resolver)(asn1p_value_t *, void *rarg),
void *rarg);
+int asn1p_value_compare(const asn1p_value_t *, const asn1p_value_t *);
+void asn1p_value_set_source(asn1p_value_t *, struct asn1p_module_s *, int line);
#endif /* ASN1_PARSER_VALUE_H */