1 /******************************************************************************
2 * Copyright (c) 2000-2016 Ericsson Telecom AB
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/epl-v10.html
14 ******************************************************************************/
15 #include "subtypestuff.hh"
16 #include "../common/dbgnew.hh"
17 #include "Identifier.hh"
21 #include "CompilerError.hh"
22 #include "Valuestuff.hh"
23 #include "ttcn3/TtcnTemplate.hh"
24 #include "ttcn3/Templatestuff.hh"
25 #include "ttcn3/PatternString.hh"
26 #include "PredefFunc.hh"
33 tribool
operator||(tribool a
, tribool b
)
35 static tribool truth_table
[3][3] = { {TFALSE
, TUNKNOWN
, TTRUE
}, {TUNKNOWN
, TUNKNOWN
, TTRUE
}, {TTRUE
, TTRUE
, TTRUE
} };
36 return truth_table
[a
][b
];
39 tribool
operator&&(tribool a
, tribool b
)
41 static tribool truth_table
[3][3] = { {TFALSE
, TFALSE
, TFALSE
}, {TFALSE
, TUNKNOWN
, TUNKNOWN
}, {TFALSE
, TUNKNOWN
, TTRUE
} };
42 return truth_table
[a
][b
];
45 tribool
operator!(tribool tb
)
47 static tribool truth_table
[3] = { TTRUE
, TUNKNOWN
, TFALSE
};
48 return truth_table
[tb
];
51 tribool
TRIBOOL(bool b
) { return ( b
? TTRUE
: TFALSE
); }
53 string
to_string(const tribool
& tb
)
57 return string("false");
59 return string("true");
61 return string("unknown");
63 FATAL_ERROR("print(tribool)");
68 ////////////////////////////////////////////////////////////////////////////////
70 const int_limit_t
int_limit_t::minimum(int_limit_t::MINUS_INFINITY
);
72 const int_limit_t
int_limit_t::maximum(int_limit_t::PLUS_INFINITY
);
74 int_limit_t::int_limit_t(int_limit_type_t p_type
):
82 FATAL_ERROR("int_limit_t::int_limit_t(int_limit_type_t)");
86 bool int_limit_t::operator<(const int_limit_t
& right
) const
90 return (right
.type
!=MINUS_INFINITY
);
92 return ( (right
.type
==PLUS_INFINITY
) || ( (right
.type
==NUMBER
) && (value
<right
.value
) ) );
96 FATAL_ERROR("int_limit_t::operator<()");
100 bool int_limit_t::operator==(const int_limit_t
& right
) const
102 if (type
==NUMBER
) return ( (right
.type
==NUMBER
) && (value
==right
.value
) );
103 else return (type
==right
.type
);
106 bool int_limit_t::is_adjacent(const int_limit_t
& other
) const
108 return ( (type
==NUMBER
) && (other
.type
==NUMBER
) && ((value
+1)==other
.value
) );
111 int_val_t
int_limit_t::get_value() const
113 if (type
!=NUMBER
) FATAL_ERROR("int_limit_t::get_value()");
117 int_limit_t
int_limit_t::next() const
119 return ( (type
==NUMBER
) ? int_limit_t(value
+1) : *this );
122 int_limit_t
int_limit_t::previous() const
124 return ( (type
==NUMBER
) ? int_limit_t(value
-1) : *this );
127 void int_limit_t::check_single_value() const
129 if (type
!=NUMBER
) FATAL_ERROR("int_limit_t::check_single_value()");
132 void int_limit_t::check_interval_start() const
134 if (type
==PLUS_INFINITY
) FATAL_ERROR("int_limit_t::check_interval_start()");
137 void int_limit_t::check_interval_end() const
139 if (type
==MINUS_INFINITY
) FATAL_ERROR("int_limit_t::check_interval_end()");
142 string
int_limit_t::to_string() const
145 case int_limit_t::MINUS_INFINITY
:
146 return string("-infinity");
147 case int_limit_t::NUMBER
:
148 return value
.t_str();
149 case int_limit_t::PLUS_INFINITY
:
150 return string("infinity");
152 FATAL_ERROR("int_limit_t::print()");
157 ////////////////////////////////////////////////////////////////////////////////
159 const size_limit_t
size_limit_t::minimum(0);
161 const size_limit_t
size_limit_t::maximum(INFINITE_SIZE
);
163 bool size_limit_t::operator<(const size_limit_t
& right
) const
165 return ( !infinity
&& ( right
.infinity
|| (size
<right
.size
) ) );
168 bool size_limit_t::operator==(const size_limit_t
& right
) const
170 return ( (infinity
==right
.infinity
) && (infinity
|| (size
==right
.size
)) );
173 bool size_limit_t::is_adjacent(const size_limit_t
& other
) const
175 return ( !infinity
&& !other
.infinity
&& (size
+1==other
.size
) );
178 size_t size_limit_t::get_size() const
180 if (infinity
) FATAL_ERROR("size_limit_t::get_size()");
184 size_limit_t
size_limit_t::next() const
186 return ( infinity
? *this : size_limit_t(size
+1) );
189 size_limit_t
size_limit_t::previous() const
191 if (size
==0) FATAL_ERROR("size_limit_t::previous()");
192 return ( infinity
? *this : size_limit_t(size
-1) );
195 void size_limit_t::check_single_value() const
197 if (infinity
) FATAL_ERROR("size_limit_t::check_single_value()");
200 void size_limit_t::check_interval_start() const
202 if (infinity
) FATAL_ERROR("size_limit_t::check_interval_start()");
205 string
size_limit_t::to_string() const
207 if (infinity
) return string("infinity");
208 return Int2string((Int
)size
);
211 int_limit_t
size_limit_t::to_int_limit() const
213 if (infinity
) return int_limit_t(int_limit_t::PLUS_INFINITY
);
214 return int_limit_t(int_val_t((Int
)size
)); // FIXME: size_t -> Int
217 ////////////////////////////////////////////////////////////////////////////////
219 const short int char_limit_t::max_char
= 127;
221 const char_limit_t
char_limit_t::minimum(0);
223 const char_limit_t
char_limit_t::maximum(max_char
);
225 bool char_limit_t::is_valid_value(short int p_chr
)
227 return ( (p_chr
>=0) && (p_chr
<=max_char
) );
230 char_limit_t::char_limit_t(short int p_chr
): chr(p_chr
)
232 if ( (chr
<0) || (chr
>max_char
) ) FATAL_ERROR("char_limit_t::char_limit_t()");
235 char_limit_t
char_limit_t::next() const
237 if (chr
>=max_char
) FATAL_ERROR("char_limit_t::next()");
238 return char_limit_t(chr
+1);
241 char_limit_t
char_limit_t::previous() const
243 if (chr
<=0) FATAL_ERROR("char_limit_t::previous()");
244 return char_limit_t(chr
-1);
247 string
char_limit_t::to_string() const
249 return string((char)chr
).get_stringRepr();
252 ////////////////////////////////////////////////////////////////////////////////
254 void universal_char_limit_t::check_value() const
256 if (code_point
>max_code_point
) FATAL_ERROR("universal_char_limit_t::check_value()");
259 unsigned int universal_char_limit_t::uchar2codepoint(const ustring::universal_char
& uchr
)
261 return ( (((unsigned int)uchr
.group
)<<24) + (((unsigned int)uchr
.plane
)<<16) + (((unsigned int)uchr
.row
)<<8) + ((unsigned int)uchr
.cell
) );
264 ustring::universal_char
universal_char_limit_t::codepoint2uchar(unsigned int cp
)
266 ustring::universal_char uchr
;
267 uchr
.cell
= (unsigned char)(cp
& 0xFF);
268 uchr
.row
= (unsigned char)((cp
>>8) & 0xFF);
269 uchr
.plane
= (unsigned char)((cp
>>16) & 0xFF);
270 uchr
.group
= (unsigned char)((cp
>>24) & 0xFF);
274 const unsigned int universal_char_limit_t::max_code_point
= 0x7FFFFFFF;
276 const universal_char_limit_t
universal_char_limit_t::minimum(0);
278 const universal_char_limit_t
universal_char_limit_t::maximum(max_code_point
);
280 bool universal_char_limit_t::is_valid_value(const ustring::universal_char
& p_uchr
)
282 return (uchar2codepoint(p_uchr
)<=max_code_point
);
285 universal_char_limit_t
universal_char_limit_t::next() const
287 if (code_point
>=max_code_point
) FATAL_ERROR("universal_char_limit_t::next()");
288 return universal_char_limit_t(code_point
+1);
291 universal_char_limit_t
universal_char_limit_t::previous() const
293 if (code_point
<=0) FATAL_ERROR("universal_char_limit_t::previous()");
294 return universal_char_limit_t(code_point
-1);
297 string
universal_char_limit_t::to_string() const
299 ustring::universal_char uc
= codepoint2uchar(code_point
);
300 return ustring(1,&uc
).get_stringRepr();
303 ////////////////////////////////////////////////////////////////////////////////
305 const real_limit_t
real_limit_t::minimum(make_ttcn3float(-REAL_INFINITY
));
307 const real_limit_t
real_limit_t::maximum(make_ttcn3float(REAL_INFINITY
));
309 void real_limit_t::check_value() const
311 if (value
!=value
) FATAL_ERROR("real_limit_t::check_value(): cannot be NaN");
312 if ( (value
==-REAL_INFINITY
) && (type
==LOWER
) ) FATAL_ERROR("real_limit_t::check_value(): cannot be -infinity.lower");
313 if ( (value
==REAL_INFINITY
) && (type
==UPPER
) ) FATAL_ERROR("real_limit_t::check_value(): cannot be infinity.upper");
316 bool real_limit_t::operator<(const real_limit_t
& right
) const
321 return ( (v1
<v2
) || ((v1
==v2
)&&(type
<right
.type
)) );
324 bool real_limit_t::operator==(const real_limit_t
& right
) const
329 return ( (v1
==v2
) && (type
==right
.type
) );
332 bool real_limit_t::is_adjacent(const real_limit_t
& other
) const
337 return ( (v1
==v2
) && (((type
==LOWER
)&&(other
.type
==EXACT
)) || ((type
==EXACT
)&&(other
.type
==UPPER
))) );
340 real_limit_t
real_limit_t::next() const
344 return real_limit_t(value
);
347 return real_limit_t(value
, UPPER
);
349 FATAL_ERROR("real_limit_t::next()");
353 real_limit_t
real_limit_t::previous() const
358 return real_limit_t(value
, LOWER
);
360 return real_limit_t(value
);
362 FATAL_ERROR("real_limit_t::previous()");
366 void real_limit_t::check_single_value() const
368 if (type
!=EXACT
) FATAL_ERROR("real_limit_t::check_single_value()");
371 void real_limit_t::check_interval_start() const
373 if (type
==LOWER
) FATAL_ERROR("real_limit_t::check_interval_start()");
376 void real_limit_t::check_interval_end() const
378 if (type
==UPPER
) FATAL_ERROR("real_limit_t::check_interval_end()");
381 string
real_limit_t::to_string() const
384 if (type
!=EXACT
) ret_val
+= '!';
385 ret_val
+= Real2string(value
);
389 ////////////////////////////////////////////////////////////////////////////////
391 bool convert_int_to_size(const RangeListConstraint
<int_limit_t
>& int_range
, RangeListConstraint
<size_limit_t
>& size_range
)
393 size_range
= RangeListConstraint
<size_limit_t
>();
394 size_range
.intervals
= int_range
.intervals
;
395 size_range
.values
= dynamic_array
<size_limit_t
>(int_range
.values
.size());
396 for (size_t i
=0; i
<int_range
.values
.size(); i
++) {
397 const int_limit_t
& il
= int_range
.values
[i
];
399 switch (il
.get_type()) {
400 case int_limit_t::MINUS_INFINITY
:
401 size_range
= RangeListConstraint
<size_limit_t
>(size_limit_t::minimum
, size_limit_t::maximum
);
403 case int_limit_t::NUMBER
: {
404 int_val_t number
= il
.get_value();
405 if ((number
<0) || !number
.is_native_fit()) {
406 size_range
= RangeListConstraint
<size_limit_t
>(size_limit_t::minimum
, size_limit_t::maximum
);
409 sl
= size_limit_t((size_t)number
.get_val());
411 case int_limit_t::PLUS_INFINITY
:
412 sl
= size_limit_t::maximum
;
415 FATAL_ERROR("RangeListConstraint::convert_int_to_size()");
417 size_range
.values
.add(sl
);
422 ////////////////////////////////////////////////////////////////////////////////
424 bool RealRangeListConstraint::is_element(const ttcn3float
& r
) const
426 if (r
!=r
) // this is a NaN value
429 return rlc
.is_element(real_limit_t(r
));
432 RealRangeListConstraint
RealRangeListConstraint::set_operation(const RealRangeListConstraint
& other
, bool is_union
) const
434 RealRangeListConstraint ret_val
;
435 ret_val
.rlc
= rlc
.set_operation(other
.rlc
, is_union
);
436 ret_val
.has_nan
= is_union
? (has_nan
|| other
.has_nan
) : (has_nan
&& other
.has_nan
);
440 RealRangeListConstraint
RealRangeListConstraint::operator~() const
442 RealRangeListConstraint ret_val
;
444 ret_val
.has_nan
= !has_nan
;
448 string
RealRangeListConstraint::to_string() const
452 ret_val
+= rlc
.to_string(false);
454 if (rlc
.is_empty()!=TTRUE
) ret_val
+= ',';
461 bool RealRangeListConstraint::is_upper_limit_infinity () const
463 return rlc
.is_upper_limit_infinity();
466 bool RealRangeListConstraint::is_lower_limit_infinity () const
468 return rlc
.is_lower_limit_infinity();
471 ////////////////////////////////////////////////////////////////////////////////
473 string
BooleanListConstraint::to_string() const
477 if (values
&BC_FALSE
) ret_val
+= "false";
478 if (values
==BC_ALL
) ret_val
+= ',';
479 if (values
&BC_TRUE
) ret_val
+= "true";
484 ////////////////////////////////////////////////////////////////////////////////
486 string
VerdicttypeListConstraint::to_string() const
488 static const size_t verdict_count
= 5;
489 static const char* verdict_names
[verdict_count
] = { "none", "pass", "inconc", "fail", "error" };
492 bool has_value
= false;
493 for (size_t i
=VC_NONE
,idx
=0; (i
<VC_ALL
)&&(idx
<verdict_count
); i
<<=1,idx
++)
496 if (has_value
) ret_val
+= ',';
497 ret_val
+= verdict_names
[idx
];
505 ////////////////////////////////////////////////////////////////////////////////
507 tribool
StringPatternConstraint::match(const string
& str
) const
509 string patt
= pattern
->get_full_str();
510 if (patt
.size()==0) return TRIBOOL(str
.size()==0);
511 string
*result
= regexp(str
, string('(')+patt
+string(')'), 0);
512 bool rv
= (result
->size()!=0);
517 string
StringPatternConstraint::to_string() const
520 ret_val
+= "pattern(";
521 ret_val
+= pattern
->get_full_str();
526 ////////////////////////////////////////////////////////////////////////////////
527 // constraint classes for structured types
529 void ValueList::clean_up()
534 void ValueList::copy_content(const ValueList
& other
)
536 for (size_t j
=0; j
<other
.values
.size(); j
++) values
.add(other
.values
[j
]);
539 tribool
ValueList::is_equal(const ValueList
& other
) const
541 if (values
.size()!=other
.values
.size()) return TFALSE
;
542 dynamic_array
<bool> found(other
.values
.size()); // helper to skip unnecessary comparisons
543 for (size_t j
=0; j
<other
.values
.size(); j
++) found
[j
] = false;
544 for (size_t i
=0; i
<values
.size(); i
++) {
545 bool found_i
= false;
546 for (size_t j
=0; j
<other
.values
.size(); j
++) {
547 if (found
[j
]) continue; // skip already found equal elements
548 if ( (values
[i
]==other
.values
[j
]) || (*(values
[i
])==*(other
.values
[j
])) ) {
554 if (!found_i
) return TFALSE
;
559 bool ValueList::is_element(Value
* v
) const
561 for (size_t i
=0; i
<values
.size(); i
++) {
562 if ( (values
[i
]==v
) || (*(values
[i
])==*v
) ) return true;
567 ValueList
ValueList::set_operation(const ValueList
& other
, bool is_union
) const
571 for (size_t i
=0; i
<values
.size(); i
++) ret_val
.values
.add(values
[i
]);
572 for (size_t i
=0; i
<other
.values
.size(); i
++) {
573 if (!is_element(other
.values
[i
])) ret_val
.values
.add(other
.values
[i
]);
576 for (size_t i
=0; i
<values
.size(); i
++) {
577 if (other
.is_element(values
[i
])) ret_val
.values
.add(values
[i
]);
583 ValueList
ValueList::operator-(const ValueList
& other
) const
586 for (size_t i
=0; i
<values
.size(); i
++) {
587 if (!other
.is_element(values
[i
])) ret_val
.values
.add(values
[i
]);
592 void ValueList::remove(const SizeRangeListConstraint
& size_constraint
, bool if_element
)
594 for (size_t i
=0; i
<values
.size(); i
++) {
595 if (size_constraint
.is_element(size_limit_t(values
[i
]->get_nof_comps()))==if_element
) {
602 string
ValueList::to_string() const
606 for (size_t i
=0; i
<values
.size(); i
++) {
607 if (i
>0) ret_val
+= ',';
608 ret_val
+= values
[i
]->create_stringRepr();
614 ////////////////////////////////////////////////////////////////////////////////
616 tribool
ValueListConstraint::is_empty() const
618 return complemented
? values
.is_full() : values
.is_empty();
622 tribool
ValueListConstraint::is_full() const
624 return complemented
? values
.is_empty() : values
.is_full();
628 tribool
ValueListConstraint::is_equal(const ValueListConstraint
& other
) const
630 return (complemented
==other
.complemented
) ? values
.is_equal(other
.values
) : TUNKNOWN
;
634 bool ValueListConstraint::is_element(Value
* v
) const
636 return complemented
^ values
.is_element(v
);
639 ValueListConstraint
ValueListConstraint::operator+(const ValueListConstraint
& other
) const
641 ValueListConstraint ret_val
;
643 if (other
.complemented
) {
644 ret_val
.complemented
= true;
645 ret_val
.values
= values
* other
.values
;
647 ret_val
.complemented
= true;
648 ret_val
.values
= values
- other
.values
;
651 if (other
.complemented
) {
652 ret_val
.complemented
= true;
653 ret_val
.values
= other
.values
- values
;
655 ret_val
.complemented
= false;
656 ret_val
.values
= values
+ other
.values
;
662 ValueListConstraint
ValueListConstraint::operator*(const ValueListConstraint
& other
) const
664 ValueListConstraint ret_val
;
666 if (other
.complemented
) {
667 ret_val
.complemented
= true;
668 ret_val
.values
= values
+ other
.values
;
670 ret_val
.complemented
= false;
671 ret_val
.values
= other
.values
- values
;
674 if (other
.complemented
) {
675 ret_val
.complemented
= false;
676 ret_val
.values
= values
- other
.values
;
678 ret_val
.complemented
= false;
679 ret_val
.values
= values
* other
.values
;
685 ValueListConstraint
ValueListConstraint::operator~() const
687 ValueListConstraint ret_val
;
688 ret_val
.complemented
= !complemented
;
689 ret_val
.values
= values
;
693 string
ValueListConstraint::to_string() const
697 ret_val
+= "(ALL except ";
698 ret_val
+= values
.to_string();
702 return values
.to_string();
705 ////////////////////////////////////////////////////////////////////////////////
707 tribool
RecofConstraint::is_empty() const
709 if ( (size_constraint
.is_empty()==TTRUE
) && (has_values
.is_empty()==TTRUE
) ) return TTRUE
;
710 if (has_values
.is_empty()==TFALSE
) return TFALSE
;
711 if (not_values
.is_empty()==TTRUE
) return TFALSE
;
712 return TUNKNOWN
; // the set of not_values may possibly cancel the size constraint set
715 tribool
RecofConstraint::is_full() const
717 if ( (size_constraint
.is_full()==TTRUE
) && (not_values
.is_empty()==TTRUE
) ) return TTRUE
;
718 if (not_values
.is_empty()==TFALSE
) return TFALSE
;
722 tribool
RecofConstraint::is_equal(const RecofConstraint
& other
) const
724 if ( (size_constraint
.is_equal(other
.size_constraint
)==TTRUE
) &&
725 (has_values
.is_equal(other
.has_values
)==TTRUE
) && (not_values
.is_equal(other
.not_values
)==TTRUE
) )
727 return TUNKNOWN
; // unknown because there's no canonical form
730 bool RecofConstraint::is_element(Value
* v
) const
732 if (size_constraint
.is_element(size_limit_t(v
->get_nof_comps()))) return !not_values
.is_element(v
);
733 return has_values
.is_element(v
);
736 // representation of two sets: [Si+Vi-Ni] where Si=size_constraint, Vi=has_values, Ni=not_values
737 // UNION: [S1+V1-N1] + [S2+V2-N2] = ... = [(S1+S2)+(V1+V2)-((~S1*N2)+(N1*~S2)+(N1*N2))]
738 // INTERSECTION: [S1+V1-N1] * [S2+V2-N2] = ... = [(S1*S2)+((S1*V2-N1)+(S2*V1-N2)+(V1*V2))-(N1+N2)]
739 RecofConstraint
RecofConstraint::set_operation(const RecofConstraint
& other
, bool is_union
) const
741 RecofConstraint ret_val
;
742 ret_val
.size_constraint
= size_constraint
.set_operation(other
.size_constraint
, is_union
);
745 ret_val
.has_values
= has_values
+ other
.has_values
;
747 ValueList vlc1
= other
.not_values
;
748 vlc1
.remove(size_constraint
, true);
750 ValueList vlc2
= not_values
;
751 vlc2
.remove(other
.size_constraint
, true);
752 // ((~S1*N2)+(N1*~S2)+(N1*N2))
753 ret_val
.not_values
= vlc1
+ vlc2
+ (not_values
* other
.not_values
);
754 } else { // intersection
756 ValueList vlc1
= has_values
;
757 vlc1
.remove(other
.size_constraint
, false);
758 vlc1
= vlc1
- other
.not_values
;
760 ValueList vlc2
= other
.has_values
;
761 vlc2
.remove(size_constraint
, false);
762 vlc2
= vlc2
- not_values
;
763 // (S1*V2-N1)+(S2*V1-N2)+(V1*V2)
764 ret_val
.has_values
= (has_values
* other
.has_values
) + vlc1
+ vlc2
;
765 // union of not_values
766 ret_val
.not_values
= not_values
+ other
.not_values
;
768 // drop the intersection, holes and points cancel each other
769 ValueList vlc
= ret_val
.has_values
* ret_val
.not_values
;
770 ret_val
.has_values
= ret_val
.has_values
- vlc
;
771 ret_val
.not_values
= ret_val
.not_values
- vlc
;
772 // drop ret_val.has_values elements that are elements of the ret_val.size_constraint set
773 ret_val
.has_values
.remove(ret_val
.size_constraint
, true);
774 // drop ret_val.not_values elements that are not elements of the ret_val.size_constraint set
775 ret_val
.not_values
.remove(ret_val
.size_constraint
, false);
779 RecofConstraint
RecofConstraint::operator~() const
781 RecofConstraint ret_val
;
782 ret_val
.size_constraint
= ~size_constraint
;
783 ret_val
.has_values
= not_values
;
784 ret_val
.not_values
= has_values
;
788 tribool
RecofConstraint::get_size_limit(bool is_upper
, size_limit_t
& limit
) const
790 if (size_constraint
.is_empty()==TTRUE
) return TFALSE
;
791 limit
= is_upper
? size_constraint
.get_maximal() : size_constraint
.get_minimal();
795 string
RecofConstraint::to_string() const
798 if (has_values
.is_empty()!=TTRUE
) ret_val
+= has_values
.to_string();
799 if (size_constraint
.is_empty()!=TTRUE
) {
800 if (has_values
.is_empty()!=TTRUE
) ret_val
+= " union ";
802 ret_val
+= size_constraint
.to_string();
805 if (not_values
.is_empty()!=TTRUE
) {
806 ret_val
+= " except ";
807 ret_val
+= not_values
.to_string();
813 } // namespace Common