asn1c/libasn1parser/asn1p_value.c

347 lines
8.0 KiB
C

#include <stdlib.h>
#include <string.h>
#include <errno.h>
#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;
}
return 0;
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) {
if(ref) {
asn1p_value_t *v = calloc(1, sizeof *v);
if(v) {
if(do_copy) {
v->value.reference = asn1p_ref_clone(ref);
if(v->value.reference == NULL) {
free(v);
return NULL;
}
} else {
v->value.reference = ref;
}
v->type = ATV_REFERENCED;
}
return v;
} else {
errno = EINVAL;
return NULL;
}
}
asn1p_value_t *
asn1p_value_fromconstr(asn1p_constraint_t *ct, int do_copy) {
if(ct) {
asn1p_value_t *v = calloc(1, sizeof *v);
if(v) {
if(do_copy) {
v->value.constraint
= asn1p_constraint_clone(ct);
if(v->value.constraint == NULL) {
free(v);
return NULL;
}
} else {
v->value.constraint = ct;
}
v->type = ATV_VALUESET;
}
return v;
} else {
errno = EINVAL;
return NULL;
}
}
asn1p_value_t *
asn1p_value_frombits(uint8_t *bits, int size_in_bits, int do_copy) {
if(bits) {
asn1p_value_t *v = calloc(1, sizeof *v);
assert(size_in_bits >= 0);
if(v) {
if(do_copy) {
int size = ((size_in_bits + 7) >> 3);
void *p;
p = malloc(size + 1);
if(p) {
memcpy(p, bits, size);
((char *)p)[size] = '\0'; /* JIC */
} else {
free(v);
return NULL;
}
v->value.binary_vector.bits = p;
} else {
v->value.binary_vector.bits = (void *)bits;
}
v->value.binary_vector.size_in_bits = size_in_bits;
v->type = ATV_BITVECTOR;
}
return v;
} else {
errno = EINVAL;
return NULL;
}
}
asn1p_value_t *
asn1p_value_frombuf(char *buffer, int size, int do_copy) {
if(buffer) {
asn1p_value_t *v = calloc(1, sizeof *v);
assert(size >= 0);
if(v) {
if(do_copy) {
void *p = malloc(size + 1);
if(p) {
memcpy(p, buffer, size);
((char *)p)[size] = '\0'; /* JIC */
} else {
free(v);
return NULL;
}
v->value.string.buf = p;
} else {
v->value.string.buf = (uint8_t *)buffer;
}
v->value.string.size = size;
v->type = ATV_STRING;
}
return v;
} else {
errno = EINVAL;
return NULL;
}
}
asn1p_value_t *
asn1p_value_fromdouble(double d) {
asn1p_value_t *v = calloc(1, sizeof *v);
if(v) {
v->value.v_double = d;
v->type = ATV_REAL;
}
return v;
}
asn1p_value_t *
asn1p_value_fromint(asn1c_integer_t i) {
asn1p_value_t *v = calloc(1, sizeof *v);
if(v) {
v->value.v_integer = i;
v->type = ATV_INTEGER;
}
return v;
}
asn1p_value_t *
asn1p_value_fromtype(asn1p_expr_t *expr) {
asn1p_value_t *v = calloc(1, sizeof *v);
if(v) {
v->value.v_type = expr;
v->type = ATV_TYPE;
expr->ref_cnt++;
}
return v;
}
asn1p_value_t *
asn1p_value_clone(asn1p_value_t *v) {
return asn1p_value_clone_with_resolver(v, 0, 0);
}
asn1p_value_t *
asn1p_value_clone_with_resolver(asn1p_value_t *v,
asn1p_value_t *(*resolver)(asn1p_value_t *, void *rarg),
void *rarg) {
asn1p_value_t *clone = NULL;
if(v) {
switch(v->type) {
case ATV_NOVALUE:
case ATV_NULL:
return calloc(1, sizeof(*clone));
case ATV_REAL:
return asn1p_value_fromdouble(v->value.v_double);
case ATV_TYPE:
return asn1p_value_fromtype(v->value.v_type);
case ATV_INTEGER:
case ATV_MIN:
case ATV_MAX:
case ATV_FALSE:
case ATV_TRUE:
case ATV_TUPLE:
case ATV_QUADRUPLE:
clone = asn1p_value_fromint(v->value.v_integer);
if(clone) clone->type = v->type;
return clone;
case ATV_STRING:
clone = asn1p_value_frombuf((char *)v->value.string.buf,
v->value.string.size, 1);
if(clone) clone->type = v->type;
return clone;
case ATV_UNPARSED:
clone = asn1p_value_frombuf((char *)v->value.string.buf,
v->value.string.size, 1);
if(clone) clone->type = ATV_UNPARSED;
return clone;
case ATV_BITVECTOR:
return asn1p_value_frombits(v->value.binary_vector.bits,
v->value.binary_vector.size_in_bits, 1);
case ATV_REFERENCED:
if(resolver) {
clone = resolver(v, rarg);
if(clone) return clone;
else if(errno != ESRCH) return NULL;
}
return asn1p_value_fromref(v->value.reference, 1);
case ATV_VALUESET:
if(resolver) {
clone = resolver(v, rarg);
if(clone) return clone;
else if(errno != ESRCH) return NULL;
}
return asn1p_value_fromconstr(v->value.constraint, 1);
case ATV_CHOICE_IDENTIFIER: {
char *id = v->value.choice_identifier.identifier;
clone = calloc(1, sizeof(*clone));
if(!clone) return NULL;
clone->type = v->type;
id = strdup(id);
if(!id) { asn1p_value_free(clone); return NULL; }
clone->value.choice_identifier.identifier = id;
v = asn1p_value_clone(v->value.choice_identifier.value);
if(!v) { asn1p_value_free(clone); return NULL; }
clone->value.choice_identifier.value = v;
return clone;
}
}
assert(!"UNREACHABLE");
}
return v;
}
void
asn1p_value_free(asn1p_value_t *v) {
if(v) {
switch(v->type) {
case ATV_NOVALUE:
case ATV_NULL:
break;
case ATV_TYPE:
asn1p_expr_free(v->value.v_type);
break;
case ATV_REAL:
case ATV_INTEGER:
case ATV_MIN:
case ATV_MAX:
case ATV_FALSE:
case ATV_TRUE:
case ATV_TUPLE:
case ATV_QUADRUPLE:
/* No freeing necessary */
break;
case ATV_STRING:
case ATV_UNPARSED:
assert(v->value.string.buf);
free(v->value.string.buf);
break;
case ATV_BITVECTOR:
assert(v->value.binary_vector.bits);
free(v->value.binary_vector.bits);
break;
case ATV_REFERENCED:
asn1p_ref_free(v->value.reference);
break;
case ATV_VALUESET:
asn1p_constraint_free(v->value.constraint);
break;
case ATV_CHOICE_IDENTIFIER:
free(v->value.choice_identifier.identifier);
asn1p_value_free(v->value.choice_identifier.value);
break;
}
memset(v, 0, sizeof(*v));
free(v);
}
}