Initial version of asn1c
[com/asn1c.git] / libasn1parser / asn1p_constr.c
diff --git a/libasn1parser/asn1p_constr.c b/libasn1parser/asn1p_constr.c
new file mode 100644 (file)
index 0000000..03dafe5
--- /dev/null
@@ -0,0 +1,240 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <assert.h>
+
+#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((a && b));
+
+    if(a->type != b->type)
+        return -1;
+
+    /* Currently we only check VALUESET as a reference */
+    if(a->type == ACT_EL_TYPE) {
+        return strcmp(a->containedSubtype->value.v_type->reference->components[0].name,
+                      b->containedSubtype->value.v_type->reference->components[0].name);
+    }
+
+    return 0;
+}
+
+asn1p_constraint_t *
+asn1p_constraint_new(int _lineno, asn1p_module_t *mod) {
+       asn1p_constraint_t *ct;
+
+       ct = calloc(1, sizeof(*ct));
+       if(ct) {
+               ct->_lineno = _lineno;
+               ct->module = mod;
+       }
+
+       return ct;
+}
+
+
+void
+asn1p_constraint_free(asn1p_constraint_t *ct) {
+       if(ct) {
+
+               asn1p_value_free(ct->containedSubtype);
+               asn1p_value_free(ct->value);
+               asn1p_value_free(ct->range_start);
+               asn1p_value_free(ct->range_stop);
+
+               if(ct->elements) {
+                       while(ct->el_count--) {
+                               asn1p_constraint_free(
+                                       ct->elements[ct->el_count]);
+                       }
+                       free(ct->elements);
+               }
+
+               free(ct);
+       }
+}
+
+asn1p_constraint_t *
+asn1p_constraint_clone(asn1p_constraint_t *src) {
+       return asn1p_constraint_clone_with_resolver(src, 0, 0);
+}
+
+asn1p_constraint_t *
+asn1p_constraint_clone_with_resolver(asn1p_constraint_t *src,
+               asn1p_value_t *(*vr)(asn1p_value_t *, void *varg), void *varg) {
+       asn1p_constraint_t *clone;
+
+#define        CLONE(field, func)      do { if(src->field) {                   \
+                       clone->field = func(src->field, vr, varg);      \
+                       if(clone->field == NULL) {                      \
+                               asn1p_constraint_free(clone);           \
+                               return NULL;                            \
+                       }                                               \
+               } } while(0)
+
+       clone = asn1p_constraint_new(src->_lineno, src->module);
+       if(clone) {
+               unsigned int i;
+
+               clone->type = src->type;
+               clone->presence = src->presence;
+               CLONE(containedSubtype, asn1p_value_clone_with_resolver);
+               CLONE(value,            asn1p_value_clone_with_resolver);
+               CLONE(range_start,      asn1p_value_clone_with_resolver);
+               CLONE(range_stop,       asn1p_value_clone_with_resolver);
+
+               for(i = 0; i < src->el_count; i++) {
+                       asn1p_constraint_t *t;
+                       t = asn1p_constraint_clone_with_resolver(src->elements[i], vr, varg);
+                       if(!t) {
+                               asn1p_constraint_free(clone);
+                               return NULL;
+                       }
+                       if(asn1p_constraint_insert(clone, t)) {
+                               asn1p_constraint_free(clone);
+                               asn1p_constraint_free(t);
+                               return NULL;
+                       }
+               }
+               assert(clone->el_count == src->el_count);
+               clone->_lineno = src->_lineno;
+       }
+
+       return clone;
+}
+
+/*
+ * Make sure there's enough space to add an element.
+ */
+static int
+asn1p_constraint_make_memory(asn1p_constraint_t *ct) {
+       if(ct->el_count == ct->el_size) {
+               unsigned int newsize = ct->el_size ? ct->el_size << 2 : 4;
+               void *p;
+               p = realloc(ct->elements, newsize * sizeof(ct->elements[0]));
+               if(p) {
+                       ct->elements = p;
+                       ct->el_size = newsize;
+               } else {
+                       return -1;
+               }
+       }
+       return 0;
+}
+
+int
+asn1p_constraint_insert(asn1p_constraint_t *into, asn1p_constraint_t *what) {
+       assert(into);
+       assert(what);
+
+       if(asn1p_constraint_make_memory(into))
+               return -1;
+
+       into->elements[into->el_count++] = what;
+       what->parent_ct = into;
+
+       return 0;
+}
+
+int
+asn1p_constraint_prepend(asn1p_constraint_t *before, asn1p_constraint_t *what) {
+       assert(before);
+       assert(what);
+
+       if(asn1p_constraint_make_memory(before))
+               return -1;
+
+       memmove(&before->elements[1], &before->elements[0],
+               before->el_count * sizeof(before->elements[0]));
+
+       before->elements[0] = what;
+       before->el_count++;
+       what->parent_ct = before;
+
+       return 0;
+}
+
+
+const char *
+asn1p_constraint_type2str(enum asn1p_constraint_type_e type) {
+       switch(type) {
+       case ACT_INVALID:
+               return "INVALID";
+       case ACT_EL_TYPE:
+               return "ContainedSubtype";
+       case ACT_EL_VALUE:
+               return "SingleValue";
+       case ACT_EL_RANGE:
+       case ACT_EL_LLRANGE:
+       case ACT_EL_RLRANGE:
+       case ACT_EL_ULRANGE:
+               return "ValueRange";
+       case ACT_EL_EXT:
+               return "...";
+       case ACT_CT_SIZE:
+               return "SizeConstraint";
+       case ACT_CT_FROM:
+               return "PermittedAlphabet";
+       case ACT_CT_WCOMP:
+               return "SingleTypeConstraint";
+       case ACT_CT_WCOMPS:
+               return "MultipleTypeConstraints";
+       case ACT_CT_CTDBY:
+               return "UserDefinedConstraint";
+       case ACT_CT_CTNG:
+               return "ContentsConstraint";
+       case ACT_CT_PATTERN:
+               return "PatternConstraint";
+       case ACT_CA_SET:
+               return "SET";
+       case ACT_CA_CRC:
+               return "ComponentRelationConstraint";
+       case ACT_CA_CSV:
+               return "CSV";
+       case ACT_CA_UNI:
+               return "UNION";
+       case ACT_CA_INT:
+               return "INTERSECTION";
+       case ACT_CA_EXC:
+               return "EXCEPT";
+       case ACT_CA_AEX:
+               return "ALL EXCEPT";
+       }
+       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;
+}
+