📄 asn1fix_crange.c
字号:
#include "asn1fix_internal.h"#include "asn1fix_constraint.h"#include "asn1fix_crange.h"#undef FATAL#define FATAL(fmt, args...) do { \ fprintf(stderr, "FATAL: "); \ fprintf(stderr, fmt, ##args); \ fprintf(stderr, "\n"); \ } while(0)voidasn1constraint_range_free(asn1cnst_range_t *cr) { if(cr) { int i; if(cr->elements) { for(i = 0; i < cr->el_count; i++) asn1constraint_range_free(cr->elements[i]); free(cr->elements); } free(cr); }}#define _range_free(foo) asn1constraint_range_free(foo)static asn1cnst_range_t *_range_new() { asn1cnst_range_t *r; r = calloc(1, sizeof(*r)); if(r) { r->left.type = ARE_MIN; r->right.type = ARE_MAX; } return r;}static void _range_remove_element(asn1cnst_range_t *range, int idx) { assert(idx >= 0 && idx < range->el_count); assert(!range->elements[idx]->elements); _range_free(range->elements[idx]); memmove(&range->elements[idx], &range->elements[idx + 1], (range->el_count - idx - 1) * sizeof(range->elements[0]) ); range->el_count--; range->elements[range->el_count] = 0; /* JIC */ if(range->el_count == 0) { range->el_size = 0; free(range->elements); range->elements = 0; }}static int _range_insert(asn1cnst_range_t *into, asn1cnst_range_t *cr) { assert(!cr->elements); if(into->el_count == into->el_size) { void *p; int n = into->el_size?(into->el_size << 1):4; p = realloc(into->elements, n * sizeof(into->elements[0])); if(p) { into->el_size = n; into->elements = p; } else { assert(p); return -1; } } into->elements[into->el_count++] = cr; return 0;}static asn1cnst_range_t *_range_clone(const asn1cnst_range_t *range) { asn1cnst_range_t *clone; int i; clone = _range_new(); if(!clone) return NULL; *clone = *range; clone->elements = 0; clone->el_count = 0; clone->el_size = 0; for(i = 0; i < range->el_count; i++) { asn1cnst_range_t *r = _range_clone(range->elements[i]); if(!r || _range_insert(clone, r)) { _range_free(clone); _range_free(r); return NULL; } } return clone;}static int_edge_compare(const asn1cnst_edge_t *el, const asn1cnst_edge_t *er) { switch(el->type) { case ARE_MIN: switch(er->type) { case ARE_MIN: return 0; case ARE_MAX: return -1; case ARE_VALUE: return -1; } break; case ARE_MAX: switch(er->type) { case ARE_MIN: return 1; case ARE_MAX: return 0; case ARE_VALUE: return 1; } break; case ARE_VALUE: switch(er->type) { case ARE_MIN: return 1; case ARE_MAX: return -1; case ARE_VALUE: if(el->value < er->value) return -1; if(el->value > er->value) return 1; return 0; } break; } return 0;}static int_range_compare(const void *a, const void *b) { const asn1cnst_range_t *ra = *(const asn1cnst_range_t * const *)a; const asn1cnst_range_t *rb = *(const asn1cnst_range_t * const *)b; int ret; ret = _edge_compare(&ra->left, &rb->left); if(!ret) { ret = _edge_compare(&ra->right, &rb->right); } return ret;}static char *_edge_value(const asn1cnst_edge_t *edge) { static char buf[128]; *buf = '\0'; switch(edge->type) { case ARE_MIN: strcpy(buf, "MIN"); break; case ARE_MAX: strcpy(buf, "MAX"); break; case ARE_VALUE: snprintf(buf, sizeof(buf), "%" PRIdASN, edge->value); } return buf;}static void_range_print(const asn1cnst_range_t *range) { if(_edge_compare(&range->left, &range->right)) { printf("(%s.", _edge_value(&range->left)); printf(".%s", _edge_value(&range->right)); } else { printf("(%s", _edge_value(&range->left)); } if(range->extensible) { printf(",...)"); } else { printf(")"); } if(range->incompatible) printf("/I"); if(range->not_PER_visible) printf("/!V"); if(range->el_count) { int i; printf("-=>"); for(i = 0; i < range->el_count; i++) _range_print(range->elements[i]); }}static int_edge_is_within(const asn1cnst_range_t *range, const asn1cnst_edge_t *edge) { int i; for(i = -1; i < range->el_count; i++) { const asn1cnst_range_t *r; if(i == -1) { if(range->el_count) continue; r = range; } else { r = range->elements[i]; } if(_edge_compare(&r->left, edge) <= 0 && _edge_compare(&r->right, edge) >= 0) return 1; } return 0;}static int_check_edges_within(const asn1cnst_range_t *range, const asn1cnst_range_t *r) { if(!_edge_is_within(range, &r->left)) { FATAL("Constraint value %s at line %d " "is not within " "a parent constraint range", _edge_value(&r->left), r->left.lineno ); return -1; } if(!_edge_is_within(range, &r->right)) { FATAL("Constraint value %s at line %d " "is not within " "a parent constraint range", _edge_value(&r->right), r->right.lineno ); return -1; } return 0;}static int _range_merge_in(asn1cnst_range_t *into, asn1cnst_range_t *cr) { asn1cnst_range_t *r; int prev_count = into->el_count; int i; into->not_PER_visible |= cr->not_PER_visible; into->extensible |= cr->extensible; /* * Add the element OR all its children "into". */ for(i = -1; i < cr->el_count; i++) { if(i == -1) { if(cr->el_count) continue; r = cr; } else { r = cr->elements[i]; } if(_range_insert(into, r)) { into->el_count = prev_count; /* Undo */ return -1; } } if(cr->el_count) { cr->el_count = 0; _range_free(cr); } else { /* This range is linked into "into". */ } return 0;}static int _range_fill(asn1p_value_t *val, const asn1cnst_range_t *minmax, asn1cnst_edge_t *edge, asn1cnst_range_t *range, enum asn1p_constraint_type_e type, int lineno) { unsigned char *p, *pend; edge->lineno = lineno; switch(val->type) { case ATV_INTEGER: if(type != ACT_EL_RANGE && type != ACT_CT_SIZE) { FATAL("Integer %" PRIdASN " value invalid " "for %s constraint at line %d", val->value.v_integer, asn1p_constraint_type2str(type), lineno); return -1; } edge->type = ARE_VALUE; edge->value = val->value.v_integer; return 0; case ATV_MIN: if(type != ACT_EL_RANGE && type != ACT_CT_SIZE) { FATAL("MIN invalid for %s constraint at line %d", asn1p_constraint_type2str(type), lineno); return -1; } edge->type = ARE_MIN; if(minmax) *edge = minmax->left; edge->lineno = lineno; /* Restore lineno */ return 0; case ATV_MAX: if(type != ACT_EL_RANGE && type != ACT_CT_SIZE) { FATAL("MAX invalid for %s constraint at line %d", asn1p_constraint_type2str(type), lineno); return -1; } edge->type = ARE_MAX; if(minmax) *edge = minmax->right; edge->lineno = lineno; /* Restore lineno */ return 0; case ATV_FALSE: case ATV_TRUE: if(type != ACT_EL_RANGE) { FATAL("%s is invalid for %s constraint at line %d", val->type==ATV_TRUE?"TRUE":"FALSE", asn1p_constraint_type2str(type), lineno); return -1; } edge->type = ARE_VALUE; edge->value = (val->type==ATV_TRUE); return 0; case ATV_STRING: if(type != ACT_CT_FROM) return 0; break; case ATV_REFERENCED: FATAL("Unresolved constraint element \"%s\" at line %d", asn1f_printable_reference(val->value.reference), lineno); return -1; default: FATAL("Unrecognized constraint element at line %d", lineno); return -1; } assert(val->type == ATV_STRING); p = val->value.string.buf; pend = p + val->value.string.size; if(p == pend) return 0; edge->type = ARE_VALUE; if(val->value.string.size == 1) { edge->value = *p; } else { /* * Else this is a set: * (FROM("abcdef")) * However, (FROM("abc".."def")) is forbidden. * See also 47.4.4. */ asn1c_integer_t vmin, vmax; vmin = vmax = *p; for(; p < pend; p++) { asn1cnst_range_t *nr = _range_new(); int ret; assert(nr); if(*p < vmin) vmin = *p; if(*p > vmax) vmax = *p; ret = _range_insert(range, nr); assert(ret == 0); nr->left.type = ARE_VALUE; nr->left.value = *p; nr->left.lineno = lineno; nr->right = nr->left; } edge->value = (edge == &range->right) ? vmin : vmax; } return 0;}/* * Check if ranges contain common elements. */static int_range_overlap(const asn1cnst_range_t *ra, const asn1cnst_range_t *rb) { int lr, rl; const asn1cnst_edge_t *ra_l = &ra->left; const asn1cnst_edge_t *ra_r = &ra->right; const asn1cnst_edge_t *rb_l = &rb->left; const asn1cnst_edge_t *rb_r = &rb->right; assert(_edge_compare(ra_l, ra_r) <= 0); assert(_edge_compare(rb_l, rb_r) <= 0); lr = _edge_compare(ra_l, rb_r); rl = _edge_compare(ra_r, rb_l); /* * L: |---| * R: |---| */ if(lr > 0) return 0; /* * L: |---| * R: |---| */ if(rl < 0) return 0; return 1;}/* * (MIN..20) x (10..15) = (MIN..9,10..15,16..20) */static asn1cnst_range_t *_range_split(asn1cnst_range_t *ra, const asn1cnst_range_t *rb) { asn1cnst_range_t *range, *nr; int ll, rr; assert(ra); assert(rb); assert(!ra->el_count); assert(!rb->el_count); if(!_range_overlap(ra, rb)) { errno = 0; return 0; } ll = _edge_compare(&ra->left, &rb->left); rr = _edge_compare(&ra->right, &rb->right); /* * L: |---| * R: |-------| */ if(ll >= 0 && rr <= 0) { errno = 0; return 0; } range = _range_new(); assert(range); nr = _range_new(); assert(nr); /* * L: |---... * R: |--.. */ if(ll < 0) { nr->left = ra->left; nr->right = rb->left; if(nr->right.type == ARE_VALUE) nr->right.value--; _range_insert(range, nr); nr = _range_new(); assert(nr); } /* * L: ...---| * R: ..--| */ if(rr > 0) { nr->left = rb->right; nr->right = ra->right; if(nr->left.type == ARE_VALUE) nr->left.value++; _range_insert(range, nr); nr = _range_new(); assert(nr); } /* * L: |---| * R: |-----| */ nr->left = ra->left; nr->right = ra->right; if(_edge_compare(&ra->left, &rb->left) < 0) nr->left = rb->left; if(_edge_compare(&ra->right, &rb->right) > 0) nr->right = rb->right; _range_insert(range, nr); return range;}static int_range_intersection(asn1cnst_range_t *range, const asn1cnst_range_t *with, int strict_edge_check) { int ret; int i, j; assert(!range->incompatible); /* Propagate errors */ range->extensible |= with->extensible; range->not_PER_visible |= with->not_PER_visible; range->empty_constraint |= with->empty_constraint; if(range->empty_constraint) { /* No use in intersecting empty constraints */ return 0; } /* * This is an AND operation. */ /* If this is the only element, insert it into itself as a child */ if(range->el_count == 0) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -