X-Git-Url: https://gerrit.o-ran-sc.org/r/gitweb?a=blobdiff_plain;f=libasn1parser%2Fasn1p_value.c;fp=libasn1parser%2Fasn1p_value.c;h=957b9e47108ea626d7184ce164f9a6a695004524;hb=70ee6fc793ec8e828067a3569849b6c216054497;hp=0000000000000000000000000000000000000000;hpb=59f84608ec15c016958a6e0e0ddd813f376c0925;p=com%2Fasn1c.git diff --git a/libasn1parser/asn1p_value.c b/libasn1parser/asn1p_value.c new file mode 100644 index 0000000..957b9e4 --- /dev/null +++ b/libasn1parser/asn1p_value.c @@ -0,0 +1,346 @@ +#include +#include +#include +#include + +#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); + } +} +