blob: 17618caf0067b6a4dadd6e71be6d0f3929442b81 [file] [log] [blame]
Lev Walkinb45e0672004-08-18 05:42:05 +00001#include <asn1fix_internal.h>
2#include <asn1fix_constraint.h>
3#include <asn1fix_crange.h>
4
5#undef FATAL
6#define FATAL(fmt, args...) do { \
7 fprintf(stderr, "FATAL: "); \
8 fprintf(stderr, fmt, ##args); \
9 fprintf(stderr, "\n"); \
10 } while(0)
11
12void
13asn1constraint_range_free(asn1cnst_range_t *cr) {
14 if(cr) {
15 int i;
16 if(cr->elements) {
17 for(i = 0; i < cr->el_count; i++)
18 asn1constraint_range_free(cr->elements[i]);
19 free(cr->elements);
20 }
21 free(cr);
22 }
23}
24#define _range_free(foo) asn1constraint_range_free(foo)
25
26static asn1cnst_range_t *_range_new() {
27 asn1cnst_range_t *r;
28 r = calloc(1, sizeof(*r));
29 if(r) {
30 r->left.type = ARE_MIN;
31 r->right.type = ARE_MAX;
32 }
33 return r;
34}
35
36static void _range_remove_element(asn1cnst_range_t *range, int idx) {
37 assert(idx >= 0 && idx < range->el_count);
38
39 assert(!range->elements[idx]->elements);
40
41 _range_free(range->elements[idx]);
42
43 memmove(&range->elements[idx],
44 &range->elements[idx + 1],
45 (range->el_count - idx - 1)
46 * sizeof(range->elements[0])
47 );
48 range->el_count--;
49 range->elements[range->el_count] = 0; /* JIC */
50
51 if(range->el_count == 0) {
52 range->el_size = 0;
53 free(range->elements);
54 range->elements = 0;
55 }
56}
57
58static int _range_insert(asn1cnst_range_t *into, asn1cnst_range_t *cr) {
59
60 assert(!cr->elements);
61
62 if(into->el_count == into->el_size) {
63 void *p;
64 int n = into->el_size?(into->el_size << 1):4;
65 p = realloc(into->elements, n * sizeof(into->elements[0]));
66 if(p) {
67 into->el_size = n;
68 into->elements = p;
69 } else {
70 assert(p);
71 return -1;
72 }
73 }
74
75 into->elements[into->el_count++] = cr;
76 return 0;
77}
78
79static asn1cnst_range_t *_range_clone(const asn1cnst_range_t *range) {
80 asn1cnst_range_t *clone;
81 int i;
82
83 clone = _range_new();
84 if(!clone) return NULL;
85
86 *clone = *range;
87 clone->elements = 0;
88 clone->el_count = 0;
89 clone->el_size = 0;
90
91 for(i = 0; i < range->el_count; i++) {
92 asn1cnst_range_t *r = _range_clone(range->elements[i]);
93 if(!r || _range_insert(clone, r)) {
94 _range_free(clone);
95 _range_free(r);
96 return NULL;
97 }
98 }
99
100 return clone;
101}
102
103static int
104_edge_compare(const asn1cnst_edge_t *el, const asn1cnst_edge_t *er) {
105
106 switch(el->type) {
107 case ARE_MIN:
108 switch(er->type) {
109 case ARE_MIN: return 0;
110 case ARE_MAX: return -1;
111 case ARE_VALUE: return -1;
112 }
113 break;
114 case ARE_MAX:
115 switch(er->type) {
116 case ARE_MIN: return 1;
117 case ARE_MAX: return 0;
118 case ARE_VALUE: return 1;
119 }
120 break;
121 case ARE_VALUE:
122 switch(er->type) {
123 case ARE_MIN: return 1;
124 case ARE_MAX: return -1;
125 case ARE_VALUE:
126 if(el->value < er->value)
127 return -1;
128 if(el->value > er->value)
129 return 1;
130 return 0;
131 }
132 break;
133 }
134
135 return 0;
136}
137
138static int
139_range_compare(const void *a, const void *b) {
140 const asn1cnst_range_t *ra = *(const asn1cnst_range_t * const *)a;
141 const asn1cnst_range_t *rb = *(const asn1cnst_range_t * const *)b;
142 int ret;
143
144 ret = _edge_compare(&ra->left, &rb->left);
145 if(!ret) {
146 ret = _edge_compare(&ra->right, &rb->right);
147 }
148
149 return ret;
150}
151
152static char *
153_edge_value(const asn1cnst_edge_t *edge) {
154 static char buf[128];
155 *buf = '\0';
156 switch(edge->type) {
157 case ARE_MIN: strcpy(buf, "MIN"); break;
158 case ARE_MAX: strcpy(buf, "MAX"); break;
159 case ARE_VALUE:
160 snprintf(buf, sizeof(buf), "%lld", (long long)edge->value);
161 }
162 return buf;
163}
164
165static void
166_range_print(const asn1cnst_range_t *range) {
167
168 if(_edge_compare(&range->left, &range->right)) {
169 printf("(%s.", _edge_value(&range->left));
170 printf(".%s)", _edge_value(&range->right));
171 } else {
172 printf("(%s)", _edge_value(&range->left));
173 }
174
175 if(range->el_count) {
176 int i;
177 printf("-=>");
178 for(i = 0; i < range->el_count; i++)
179 _range_print(range->elements[i]);
180 }
181
182}
183
184static int
185_edge_is_within(const asn1cnst_range_t *range, const asn1cnst_edge_t *edge) {
186 int i;
187
188 for(i = -1; i < range->el_count; i++) {
189 const asn1cnst_range_t *r;
190 if(i == -1) {
191 if(range->el_count) continue;
192 r = range;
193 } else {
194 r = range->elements[i];
195 }
196 if(_edge_compare(&r->left, edge) <= 0
197 && _edge_compare(&r->right, edge) >= 0)
198 return 1;
199 }
200
201 return 0;
202}
203
204static int
205_check_edges_within(const asn1cnst_range_t *range, const asn1cnst_range_t *r) {
206
207 if(!_edge_is_within(range, &r->left)) {
208 FATAL("Constraint value %s at line %d "
209 "is not within "
210 "a parent constraint range",
211 _edge_value(&r->left),
212 r->left.lineno
213 );
214 return -1;
215 }
216
217 if(!_edge_is_within(range, &r->right)) {
218 FATAL("Constraint value %s at line %d "
219 "is not within "
220 "a parent constraint range",
221 _edge_value(&r->right),
222 r->right.lineno
223 );
224 return -1;
225 }
226
227 return 0;
228}
229
230static int _range_merge_in(asn1cnst_range_t *into, asn1cnst_range_t *cr) {
231 asn1cnst_range_t *r;
232 int prev_count = into->el_count;
233 int i;
234
235 /*
236 * Add the element OR all its children "into".
237 */
238 for(i = -1; i < cr->el_count; i++) {
239
240 if(i == -1) {
241 if(cr->el_count) continue;
242 r = cr;
243 } else {
244 r = cr->elements[i];
245 }
246
247 if(_range_insert(into, r)) {
248 into->el_count = prev_count; /* Undo */
249 return -1;
250 }
251 }
252
253 if(cr->el_count) {
254 cr->el_count = 0;
255 _range_free(cr);
256 } else {
257 /* This range is linked into "into". */
258 }
259
260 return 0;
261}
262
263static 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) {
264 unsigned char *p, *pend;
265
266 edge->lineno = lineno;
267
268 switch(val->type) {
269 case ATV_INTEGER:
270 if(type != ACT_EL_RANGE && type != ACT_CT_SIZE) {
271 FATAL("Integer %lld value invalid "
272 "for %s constraint at line %d",
273 (long long)val->value.v_integer,
274 asn1p_constraint_type2str(type), lineno);
275 return -1;
276 }
277 edge->type = ARE_VALUE;
278 edge->value = val->value.v_integer;
279 return 0;
280 case ATV_MIN:
281 if(type != ACT_EL_RANGE && type != ACT_CT_SIZE) {
282 FATAL("MIN invalid for %s constraint at line %d",
283 asn1p_constraint_type2str(type), lineno);
284 return -1;
285 }
286 edge->type = ARE_MIN;
287 if(minmax) *edge = minmax->left;
288 edge->lineno = lineno; /* Restore lineno */
289 return 0;
290 case ATV_MAX:
291 if(type != ACT_EL_RANGE && type != ACT_CT_SIZE) {
292 FATAL("MAX invalid for %s constraint at line %d",
293 asn1p_constraint_type2str(type), lineno);
294 return -1;
295 }
296 edge->type = ARE_MAX;
297 if(minmax) *edge = minmax->right;
298 edge->lineno = lineno; /* Restore lineno */
299 return 0;
300 case ATV_FALSE:
301 case ATV_TRUE:
302 if(type != ACT_EL_RANGE) {
303 FATAL("%s is invalid for %s constraint at line %d",
304 val->type==ATV_TRUE?"TRUE":"FALSE",
305 asn1p_constraint_type2str(type),
306 lineno);
307 return -1;
308 }
309 edge->type = ARE_VALUE;
310 edge->value = (val->type==ATV_TRUE);
311 return 0;
312 case ATV_STRING:
313 if(type != ACT_CT_FROM)
314 return 0;
315 break;
316 default:
317 FATAL("Unrecognized constraint element at line %d",
318 lineno);
319 return -1;
320 }
321
322 assert(val->type == ATV_STRING);
323
324 p = val->value.string.buf;
325 pend = p + val->value.string.size;
326 if(p == pend) return 0;
327
328 edge->type = ARE_VALUE;
329 if(val->value.string.size == 1) {
330 edge->value = *p;
331 } else {
332 /*
333 * Else this is a set:
334 * (FROM("abcdef"))
335 * However, (FROM("abc".."def")) is forbidden.
336 * See also 47.4.4.
337 */
338 asn1_integer_t vmin, vmax;
339 vmin = vmax = *p;
340 for(; p < pend; p++) {
341 asn1cnst_range_t *nr = _range_new();
342 int ret;
343 assert(nr);
344
345 if(*p < vmin) vmin = *p;
346 if(*p > vmax) vmax = *p;
347
348 ret = _range_insert(range, nr);
349 assert(ret == 0);
350
351 nr->left.type = ARE_VALUE;
352 nr->left.value = *p;
353 nr->left.lineno = lineno;
354 nr->right = nr->left;
355 }
356 edge->value = (edge == &range->right) ? vmin : vmax;
357 }
358
359 return 0;
360}
361
362/*
363 * Check if ranges contain common elements.
364 */
365static int
366_range_overlap(const asn1cnst_range_t *ra, const asn1cnst_range_t *rb) {
367 int lr, rl;
368 const asn1cnst_edge_t *ra_l = &ra->left;
369 const asn1cnst_edge_t *ra_r = &ra->right;
370 const asn1cnst_edge_t *rb_l = &rb->left;
371 const asn1cnst_edge_t *rb_r = &rb->right;
372
373 assert(_edge_compare(ra_l, ra_r) <= 0);
374 assert(_edge_compare(rb_l, rb_r) <= 0);
375
376 lr = _edge_compare(ra_l, rb_r);
377 rl = _edge_compare(ra_r, rb_l);
378
379 /*
380 * L: |---|
381 * R: |---|
382 */
383 if(lr > 0) return 0;
384
385 /*
386 * L: |---|
387 * R: |---|
388 */
389 if(rl < 0) return 0;
390
391 return 1;
392}
393
394/*
395 * (MIN..20) x (10..15) = (MIN..9,10..15,16..20)
396 */
397static asn1cnst_range_t *
398_range_split(asn1cnst_range_t *ra, const asn1cnst_range_t *rb) {
399 asn1cnst_range_t *range, *nr;
400 int ll, rr;
401
402 assert(ra);
403 assert(rb);
404 assert(!ra->el_count);
405 assert(!rb->el_count);
406
407 if(!_range_overlap(ra, rb)) {
408 errno = 0;
409 return 0;
410 }
411
412 ll = _edge_compare(&ra->left, &rb->left);
413 rr = _edge_compare(&ra->right, &rb->right);
414
415 /*
416 * L: |---|
417 * R: |-------|
418 */
419 if(ll >= 0 && rr <= 0) {
420 errno = 0;
421 return 0;
422 }
423
424 range = _range_new();
425 assert(range);
426
427 nr = _range_new();
428 assert(nr);
429
430 /*
431 * L: |---...
432 * R: |--..
433 */
434 if(ll < 0) {
435 nr->left = ra->left;
436 nr->right = rb->left;
437 if(nr->right.type == ARE_VALUE)
438 nr->right.value--;
439 _range_insert(range, nr);
440 nr = _range_new();
441 assert(nr);
442 }
443
444 /*
445 * L: ...---|
446 * R: ..--|
447 */
448 if(rr > 0) {
449 nr->left = rb->right;
450 nr->right = ra->right;
451 if(nr->left.type == ARE_VALUE)
452 nr->left.value++;
453 _range_insert(range, nr);
454 nr = _range_new();
455 assert(nr);
456 }
457
458 /*
459 * L: |---|
460 * R: |-----|
461 */
462 nr->left = ra->left;
463 nr->right = ra->right;
464 if(_edge_compare(&ra->left, &rb->left) < 0)
465 nr->left = rb->left;
466 if(_edge_compare(&ra->right, &rb->right) > 0)
467 nr->right = rb->right;
468
469 _range_insert(range, nr);
470
471 return range;
472}
473
474static int
475_range_intersection(asn1cnst_range_t *range, const asn1cnst_range_t *with, int strict_edge_check) {
476 int ret;
477 int i, j;
478
479 if(with->empty_constraint || range->empty_constraint) {
480 range->empty_constraint = 1; /* Propagate error */
481 return 0;
482 }
483
484 /*
485 * This is an AND operation.
486 */
487
488 /* If this is the only element, insert it into itself as a child */
489 if(range->el_count == 0) {
490 asn1cnst_range_t *r = _range_new();
491 r->left = range->left;
492 r->right = range->right;
493 _range_insert(range, r);
494 assert(range->el_count == 1);
495 }
496
497 /*
498 * Make sure we're dealing with sane data.
499 * G.4.2.3
500 */
501 if(strict_edge_check) {
502 for(j = -1; j < with->el_count; j++) {
503
504 if(j == -1) {
505 if(with->el_count) continue;
506 if(_check_edges_within(range, with))
507 return -1;
508 } else {
509 if(_check_edges_within(range,
510 with->elements[j]))
511 return -1;
512 }
513 }
514 }
515
516 /*
517 * Split range in pieces.
518 */
519
520 for(i = 0; i < range->el_count; i++) {
521 for(j = -1; j < with->el_count; j++) {
522 const asn1cnst_range_t *wel;
523 asn1cnst_range_t *r;
524
525 if(j == -1) {
526 if(with->el_count) continue;
527 wel = with;
528 } else {
529 wel = with->elements[j];
530 }
531
532 r = _range_split(range->elements[i], wel);
533 if(r) {
534 int ec;
535 /* Substitute the current element with a split */
536 _range_remove_element(range, i);
537 assert(r->el_count);
538 for(ec = 0; ec < r->el_count; ec++) {
539 ret = _range_insert(range, r->elements[ec]);
540 assert(ret == 0);
541 }
542 r->el_count = 0;
543 _range_free(r);
544 i--;
545 break; /* Try again from this point */
546 }
547 }
548 }
549
550 assert(range->el_count);
551
552 /*
553 * Remove pieces which aren't AND-compatible "with" range.
554 */
555
556 for(i = 0; i < range->el_count; i++) {
557 for(j = -1; j < with->el_count; j++) {
558 const asn1cnst_range_t *wel;
559
560 if(j == -1) {
561 if(with->el_count) continue;
562 wel = with;
563 } else {
564 wel = with->elements[j];
565 }
566
567 if(_range_overlap(range->elements[i], wel))
568 break;
569 }
570 if(j == with->el_count) {
571 _range_remove_element(range, i);
572 i--;
573 }
574 }
575
576 if(range->el_count == 0)
577 range->empty_constraint = 1;
578
579 return 0;
580}
581
582static int
583_range_union(asn1cnst_range_t *range) {
584 int i;
585
586 qsort(range->elements, range->el_count, sizeof(range->elements[0]),
587 _range_compare);
588
589 /*
590 * The range is sorted by the start values.
591 */
592 for(i = 1; i < range->el_count; i++) {
593 asn1cnst_range_t *ra = range->elements[i - 1];
594 asn1cnst_range_t *rb = range->elements[i];
595
596 if(_range_overlap(ra, rb)) {
597 if(_edge_compare(&ra->left, &rb->left) < 0)
598 rb->left = ra->left;
599
600 if(_edge_compare(&ra->right, &rb->right) > 0)
601 rb->right = ra->right;
602 } else {
603 /*
604 * Still, range may be joined: (1..4)(5..10).
605 * This logic is valid only for whole numbers
606 * (i.e., not REAL type, but REAL constraints
607 * are not PER-visible (X.691, 9.3.12).
608 */
609 if(ra->right.type == ARE_VALUE
610 && rb->left.type == ARE_VALUE
611 && (rb->left.value - ra->right.value) == 1) {
612 /* (1..10) */
613 rb->left = ra->left;
614 } else {
615 continue;
616 }
617 }
618
619 /*
620 * Squeeze the array by removing the ra.
621 */
622 _range_remove_element(range, i - 1);
623
624 i--; /* Retry from the current point */
625 }
626
627 return 0;
628}
629
630static int
631_range_canonicalize(asn1cnst_range_t *range) {
632
633 if(range->el_count == 0) {
634 /*
635 * Switch left and right edges, make them sorted.
636 * It might be a mild warning though.
637 */
638 if(_edge_compare(&range->left, &range->right) > 0) {
639 asn1cnst_edge_t tmp = range->left;
640 range->left = range->right;
641 range->right = tmp;
642 }
643
644 if(range->elements) {
645 free(range->elements);
646 range->elements = 0;
647 }
648 range->el_size = 0;
649 return 0;
650 }
651
652 /*
653 * Remove duplicates and overlaps by merging them in.
654 */
655 _range_union(range);
656
657 /* Refine the left edge of a parent */
658 range->left = range->elements[0]->left;
659
660 /* Refine the right edge of a parent */
661 range->right = range->elements[range->el_count - 1]->right;
662
663 /* Remove the child, if it's a single one */
664 if(range->el_count == 1) {
665 _range_remove_element(range, 0);
666 }
667
668 return 0;
669}
670
671asn1cnst_range_t *
672asn1constraint_compute_PER_range(asn1p_expr_type_e expr_type, const asn1p_constraint_t *ct, enum asn1p_constraint_type_e type, const asn1cnst_range_t *minmax, int *exmet) {
673 asn1cnst_range_t *range;
674 asn1cnst_range_t *tmp;
675 asn1p_value_t *vmin;
676 asn1p_value_t *vmax;
677 int expectation_met;
678 int ret;
679 int i;
680
681 if(!exmet) {
682 exmet = &expectation_met;
683 *exmet = 0;
684 }
685
686 /*
687 * Check if the requested constraint is compatible with expression type.
688 */
689 if(asn1constraint_compatible(expr_type, type) != 1) {
690 errno = EINVAL;
691 return 0;
692 }
693
694 /* Check arguments' validity. */
695 switch(type) {
696 case ACT_EL_RANGE:
697 if(exmet == &expectation_met)
698 *exmet = 1;
699 break;
700 case ACT_CT_FROM:
701 if(!minmax) {
702 minmax = asn1constraint_default_alphabet(expr_type);
703 if(minmax) {
704 break;
705 }
706 }
707 /* Fall through */
708 case ACT_CT_SIZE:
709 if(!minmax) {
710 static asn1cnst_range_t mm;
711 mm.left.type = ARE_VALUE;
712 mm.left.value = 0;
713 mm.right.type = ARE_MAX;
714 minmax = &mm;
715 }
716 break;
717 default:
718 errno = EINVAL;
719 return 0;
720 }
721
722 if(minmax) {
723 range = _range_clone(minmax);
724 } else {
725 range = _range_new();
726 }
727
728 if(!ct || range->not_PER_visible)
729 return range;
730
731 switch(ct->type) {
732 case ACT_EL_VALUE:
733 vmin = vmax = ct->value;
734 break;
735 case ACT_EL_RANGE:
736 case ACT_EL_LLRANGE:
737 case ACT_EL_RLRANGE:
738 case ACT_EL_ULRANGE:
739 vmin = ct->range_start;
740 vmax = ct->range_stop;
741 break;
742 case ACT_EL_EXT:
743 if(!*exmet) {
744 range->not_PER_visible = 1;
745 } else {
746 range->extensible = 1;
747 }
748 return range;
749 case ACT_CT_SIZE:
750 case ACT_CT_FROM:
751 if(type == ct->type) {
752 *exmet = 1;
753 } else {
754 range->not_PER_visible = 1;
755 return range;
756 }
757 assert(ct->el_count == 1);
758 return asn1constraint_compute_PER_range(expr_type,
759 ct->elements[0], type, minmax, exmet);
760 case ACT_CA_SET: /* (10..20)(15..17) */
761 case ACT_CA_INT: /* SIZE(1..2) ^ FROM("ABCD") */
762
763 /* AND constraints, one after another. */
764 for(i = 0; i < ct->el_count; i++) {
765 tmp = asn1constraint_compute_PER_range(expr_type,
766 ct->elements[i], type,
767 ct->type==ACT_CA_SET?range:minmax, exmet);
768 if(!tmp) {
769 _range_free(range);
770 return NULL;
771 }
772
773 if(tmp->not_PER_visible) {
774 if(ct->type == ACT_CA_SET) {
775 /*
776 * X.691, #9.3.18:
777 * Ignore this separate component.
778 */
779 } else {
780 /*
781 * X.691, #9.3.19:
782 * Ignore not PER-visible INTERSECTION
783 */
784 }
785 _range_free(tmp);
786 continue;
787 }
788
789 range->extensible |= tmp->extensible;
790
791 if(tmp->extensible && type == ACT_CT_FROM) {
792 /*
793 * X.691, #9.3.10:
794 * Extensible permitted alphabet constraints
795 * are not PER-visible.
796 */
797 range->not_PER_visible = 1;
798 }
799
800 ret = _range_intersection(range, tmp,
801 ct->type == ACT_CA_SET);
802 _range_free(tmp);
803 if(ret) {
804 _range_free(range);
805 errno = EPERM;
806 return NULL;
807 }
808 _range_canonicalize(range);
809 }
810
811 return range;
812 case ACT_CA_CSV: /* SIZE(1..2, 3..4) */
813 case ACT_CA_UNI: /* SIZE(1..2) | FROM("ABCD") */
814
815 /* Merge everything. Canonicalizator will do union magic */
816 for(i = 0; i < ct->el_count; i++) {
817 tmp = asn1constraint_compute_PER_range(expr_type,
818 ct->elements[i], type, minmax, exmet);
819 if(!tmp) {
820 _range_free(range);
821 return NULL;
822 }
823
824 if(tmp->empty_constraint) {
825 /* Ignore empty constraints */
826 _range_free(tmp);
827 continue;
828 }
829
830 range->not_PER_visible |= tmp->not_PER_visible;
831 range->extensible |= tmp->extensible;
832
833 _range_merge_in(range, tmp);
834 }
835
836 _range_canonicalize(range);
837
838 if(range->not_PER_visible) {
839 /*
840 * X.691, #9.3.19:
841 * If not PER-visible constraint is part of UNION,
842 * the resulting constraint is not PER-visible.
843 */
844 _range_free(range);
845 if(minmax)
846 range = _range_clone(minmax);
847 else
848 range = _range_new();
849 }
850
851 return range;
852 case ACT_CA_EXC: /* FROM("ABCD") EXCEPT FROM("AB") */
853 /*
854 * X.691, #9.3.19:
855 * EXCEPT and the following value set is completely ignored.
856 */
857 assert(ct->el_count >= 1);
858 _range_free(range);
859 range = asn1constraint_compute_PER_range(expr_type,
860 ct->elements[0], type, minmax, exmet);
861 return range;
862 default:
863 range->not_PER_visible = 1;
864 return range;
865 }
866
867
868 if(!*exmet) {
869 /*
870 * Expectation is not met. Return the default range.
871 */
872 range->not_PER_visible = 1;
873 return range;
874 }
875
876 _range_free(range);
877 range = _range_new();
878
879 ret = _range_fill(vmin, minmax, &range->left,
880 range, type, ct->_lineno);
881 ret |= _range_fill(vmax, minmax, &range->right,
882 range, type, ct->_lineno);
883 if(ret) {
884 _range_free(range);
885 errno = EPERM;
886 return NULL;
887 }
888
889 if(minmax) {
890 asn1cnst_range_t *clone;
891
892 clone = _range_clone(minmax);
893
894 /* Constrain parent type with given data. */
895 ret = _range_intersection(clone, range, 1);
896 _range_free(range);
897 if(ret) {
898 _range_free(clone);
899 errno = EPERM;
900 return NULL;
901 }
902 range = clone;
903 }
904
905 /*
906 * Recompute elements's min/max, remove duplicates, etc.
907 */
908 _range_canonicalize(range);
909
910 return range;
911}
912