1 ///////////////////////////////////////////////////////////////////////////////
2 // Copyright (c) 2000-2015 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
7 ///////////////////////////////////////////////////////////////////////////////
8 #include "subtypestuff.hh"
9 #include "../common/dbgnew.hh"
10 #include "Identifier.hh"
14 #include "CompilerError.hh"
15 #include "Valuestuff.hh"
16 #include "ttcn3/TtcnTemplate.hh"
17 #include "ttcn3/Templatestuff.hh"
18 #include "ttcn3/PatternString.hh"
19 #include "PredefFunc.hh"
26 tribool
operator||(tribool a
, tribool b
)
28 static tribool truth_table
[3][3] = { {TFALSE
, TUNKNOWN
, TTRUE
}, {TUNKNOWN
, TUNKNOWN
, TTRUE
}, {TTRUE
, TTRUE
, TTRUE
} };
29 return truth_table
[a
][b
];
32 tribool
operator&&(tribool a
, tribool b
)
34 static tribool truth_table
[3][3] = { {TFALSE
, TFALSE
, TFALSE
}, {TFALSE
, TUNKNOWN
, TUNKNOWN
}, {TFALSE
, TUNKNOWN
, TTRUE
} };
35 return truth_table
[a
][b
];
38 tribool
operator!(tribool tb
)
40 static tribool truth_table
[3] = { TTRUE
, TUNKNOWN
, TFALSE
};
41 return truth_table
[tb
];
44 tribool
TRIBOOL(bool b
) { return ( b
? TTRUE
: TFALSE
); }
46 string
to_string(const tribool
& tb
)
50 return string("false");
52 return string("true");
54 return string("unknown");
56 FATAL_ERROR("print(tribool)");
61 ////////////////////////////////////////////////////////////////////////////////
63 const int_limit_t
int_limit_t::minimum(int_limit_t::MINUS_INFINITY
);
65 const int_limit_t
int_limit_t::maximum(int_limit_t::PLUS_INFINITY
);
67 int_limit_t::int_limit_t(int_limit_type_t p_type
):
75 FATAL_ERROR("int_limit_t::int_limit_t(int_limit_type_t)");
79 bool int_limit_t::operator<(const int_limit_t
& right
) const
83 return (right
.type
!=MINUS_INFINITY
);
85 return ( (right
.type
==PLUS_INFINITY
) || ( (right
.type
==NUMBER
) && (value
<right
.value
) ) );
89 FATAL_ERROR("int_limit_t::operator<()");
93 bool int_limit_t::operator==(const int_limit_t
& right
) const
95 if (type
==NUMBER
) return ( (right
.type
==NUMBER
) && (value
==right
.value
) );
96 else return (type
==right
.type
);
99 bool int_limit_t::is_adjacent(const int_limit_t
& other
) const
101 return ( (type
==NUMBER
) && (other
.type
==NUMBER
) && ((value
+1)==other
.value
) );
104 int_val_t
int_limit_t::get_value() const
106 if (type
!=NUMBER
) FATAL_ERROR("int_limit_t::get_value()");
110 int_limit_t
int_limit_t::next() const
112 return ( (type
==NUMBER
) ? int_limit_t(value
+1) : *this );
115 int_limit_t
int_limit_t::previous() const
117 return ( (type
==NUMBER
) ? int_limit_t(value
-1) : *this );
120 void int_limit_t::check_single_value() const
122 if (type
!=NUMBER
) FATAL_ERROR("int_limit_t::check_single_value()");
125 void int_limit_t::check_interval_start() const
127 if (type
==PLUS_INFINITY
) FATAL_ERROR("int_limit_t::check_interval_start()");
130 void int_limit_t::check_interval_end() const
132 if (type
==MINUS_INFINITY
) FATAL_ERROR("int_limit_t::check_interval_end()");
135 string
int_limit_t::to_string() const
138 case int_limit_t::MINUS_INFINITY
:
139 return string("-infinity");
140 case int_limit_t::NUMBER
:
141 return value
.t_str();
142 case int_limit_t::PLUS_INFINITY
:
143 return string("infinity");
145 FATAL_ERROR("int_limit_t::print()");
150 ////////////////////////////////////////////////////////////////////////////////
152 const size_limit_t
size_limit_t::minimum(0);
154 const size_limit_t
size_limit_t::maximum(INFINITE_SIZE
);
156 bool size_limit_t::operator<(const size_limit_t
& right
) const
158 return ( !infinity
&& ( right
.infinity
|| (size
<right
.size
) ) );
161 bool size_limit_t::operator==(const size_limit_t
& right
) const
163 return ( (infinity
==right
.infinity
) && (infinity
|| (size
==right
.size
)) );
166 bool size_limit_t::is_adjacent(const size_limit_t
& other
) const
168 return ( !infinity
&& !other
.infinity
&& (size
+1==other
.size
) );
171 size_t size_limit_t::get_size() const
173 if (infinity
) FATAL_ERROR("size_limit_t::get_size()");
177 size_limit_t
size_limit_t::next() const
179 return ( infinity
? *this : size_limit_t(size
+1) );
182 size_limit_t
size_limit_t::previous() const
184 if (size
==0) FATAL_ERROR("size_limit_t::previous()");
185 return ( infinity
? *this : size_limit_t(size
-1) );
188 void size_limit_t::check_single_value() const
190 if (infinity
) FATAL_ERROR("size_limit_t::check_single_value()");
193 void size_limit_t::check_interval_start() const
195 if (infinity
) FATAL_ERROR("size_limit_t::check_interval_start()");
198 string
size_limit_t::to_string() const
200 if (infinity
) return string("infinity");
201 return Int2string((Int
)size
);
204 int_limit_t
size_limit_t::to_int_limit() const
206 if (infinity
) return int_limit_t(int_limit_t::PLUS_INFINITY
);
207 return int_limit_t(int_val_t((Int
)size
)); // FIXME: size_t -> Int
210 ////////////////////////////////////////////////////////////////////////////////
212 const short int char_limit_t::max_char
= 127;
214 const char_limit_t
char_limit_t::minimum(0);
216 const char_limit_t
char_limit_t::maximum(max_char
);
218 bool char_limit_t::is_valid_value(short int p_chr
)
220 return ( (p_chr
>=0) && (p_chr
<=max_char
) );
223 char_limit_t::char_limit_t(short int p_chr
): chr(p_chr
)
225 if ( (chr
<0) || (chr
>max_char
) ) FATAL_ERROR("char_limit_t::char_limit_t()");
228 char_limit_t
char_limit_t::next() const
230 if (chr
>=max_char
) FATAL_ERROR("char_limit_t::next()");
231 return char_limit_t(chr
+1);
234 char_limit_t
char_limit_t::previous() const
236 if (chr
<=0) FATAL_ERROR("char_limit_t::previous()");
237 return char_limit_t(chr
-1);
240 string
char_limit_t::to_string() const
242 return string((char)chr
).get_stringRepr();
245 ////////////////////////////////////////////////////////////////////////////////
247 void universal_char_limit_t::check_value() const
249 if (code_point
>max_code_point
) FATAL_ERROR("universal_char_limit_t::check_value()");
252 unsigned int universal_char_limit_t::uchar2codepoint(const ustring::universal_char
& uchr
)
254 return ( (((unsigned int)uchr
.group
)<<24) + (((unsigned int)uchr
.plane
)<<16) + (((unsigned int)uchr
.row
)<<8) + ((unsigned int)uchr
.cell
) );
257 ustring::universal_char
universal_char_limit_t::codepoint2uchar(unsigned int cp
)
259 ustring::universal_char uchr
;
260 uchr
.cell
= (unsigned char)(cp
& 0xFF);
261 uchr
.row
= (unsigned char)((cp
>>8) & 0xFF);
262 uchr
.plane
= (unsigned char)((cp
>>16) & 0xFF);
263 uchr
.group
= (unsigned char)((cp
>>24) & 0xFF);
267 const unsigned int universal_char_limit_t::max_code_point
= 0x7FFFFFFF;
269 const universal_char_limit_t
universal_char_limit_t::minimum(0);
271 const universal_char_limit_t
universal_char_limit_t::maximum(max_code_point
);
273 bool universal_char_limit_t::is_valid_value(const ustring::universal_char
& p_uchr
)
275 return (uchar2codepoint(p_uchr
)<=max_code_point
);
278 universal_char_limit_t
universal_char_limit_t::next() const
280 if (code_point
>=max_code_point
) FATAL_ERROR("universal_char_limit_t::next()");
281 return universal_char_limit_t(code_point
+1);
284 universal_char_limit_t
universal_char_limit_t::previous() const
286 if (code_point
<=0) FATAL_ERROR("universal_char_limit_t::previous()");
287 return universal_char_limit_t(code_point
-1);
290 string
universal_char_limit_t::to_string() const
292 ustring::universal_char uc
= codepoint2uchar(code_point
);
293 return ustring(1,&uc
).get_stringRepr();
296 ////////////////////////////////////////////////////////////////////////////////
298 const real_limit_t
real_limit_t::minimum(make_ttcn3float(-REAL_INFINITY
));
300 const real_limit_t
real_limit_t::maximum(make_ttcn3float(REAL_INFINITY
));
302 void real_limit_t::check_value() const
304 if (value
!=value
) FATAL_ERROR("real_limit_t::check_value(): cannot be NaN");
305 if ( (value
==-REAL_INFINITY
) && (type
==LOWER
) ) FATAL_ERROR("real_limit_t::check_value(): cannot be -infinity.lower");
306 if ( (value
==REAL_INFINITY
) && (type
==UPPER
) ) FATAL_ERROR("real_limit_t::check_value(): cannot be infinity.upper");
309 bool real_limit_t::operator<(const real_limit_t
& right
) const
314 return ( (v1
<v2
) || ((v1
==v2
)&&(type
<right
.type
)) );
317 bool real_limit_t::operator==(const real_limit_t
& right
) const
322 return ( (v1
==v2
) && (type
==right
.type
) );
325 bool real_limit_t::is_adjacent(const real_limit_t
& other
) const
330 return ( (v1
==v2
) && (((type
==LOWER
)&&(other
.type
==EXACT
)) || ((type
==EXACT
)&&(other
.type
==UPPER
))) );
333 real_limit_t
real_limit_t::next() const
337 return real_limit_t(value
);
340 return real_limit_t(value
, UPPER
);
342 FATAL_ERROR("real_limit_t::next()");
346 real_limit_t
real_limit_t::previous() const
351 return real_limit_t(value
, LOWER
);
353 return real_limit_t(value
);
355 FATAL_ERROR("real_limit_t::previous()");
359 void real_limit_t::check_single_value() const
361 if (type
!=EXACT
) FATAL_ERROR("real_limit_t::check_single_value()");
364 void real_limit_t::check_interval_start() const
366 if (type
==LOWER
) FATAL_ERROR("real_limit_t::check_interval_start()");
369 void real_limit_t::check_interval_end() const
371 if (type
==UPPER
) FATAL_ERROR("real_limit_t::check_interval_end()");
374 string
real_limit_t::to_string() const
377 if (type
!=EXACT
) ret_val
+= '!';
378 ret_val
+= Real2string(value
);
382 ////////////////////////////////////////////////////////////////////////////////
384 bool convert_int_to_size(const RangeListConstraint
<int_limit_t
>& int_range
, RangeListConstraint
<size_limit_t
>& size_range
)
386 size_range
= RangeListConstraint
<size_limit_t
>();
387 size_range
.intervals
= int_range
.intervals
;
388 size_range
.values
= dynamic_array
<size_limit_t
>(int_range
.values
.size());
389 for (size_t i
=0; i
<int_range
.values
.size(); i
++) {
390 const int_limit_t
& il
= int_range
.values
[i
];
392 switch (il
.get_type()) {
393 case int_limit_t::MINUS_INFINITY
:
394 size_range
= RangeListConstraint
<size_limit_t
>(size_limit_t::minimum
, size_limit_t::maximum
);
396 case int_limit_t::NUMBER
: {
397 int_val_t number
= il
.get_value();
398 if ((number
<0) || !number
.is_native_fit()) {
399 size_range
= RangeListConstraint
<size_limit_t
>(size_limit_t::minimum
, size_limit_t::maximum
);
402 sl
= size_limit_t((size_t)number
.get_val());
404 case int_limit_t::PLUS_INFINITY
:
405 sl
= size_limit_t::maximum
;
408 FATAL_ERROR("RangeListConstraint::convert_int_to_size()");
410 size_range
.values
.add(sl
);
415 ////////////////////////////////////////////////////////////////////////////////
417 bool RealRangeListConstraint::is_element(const ttcn3float
& r
) const
419 if (r
!=r
) // this is a NaN value
422 return rlc
.is_element(real_limit_t(r
));
425 RealRangeListConstraint
RealRangeListConstraint::set_operation(const RealRangeListConstraint
& other
, bool is_union
) const
427 RealRangeListConstraint ret_val
;
428 ret_val
.rlc
= rlc
.set_operation(other
.rlc
, is_union
);
429 ret_val
.has_nan
= is_union
? (has_nan
|| other
.has_nan
) : (has_nan
&& other
.has_nan
);
433 RealRangeListConstraint
RealRangeListConstraint::operator~() const
435 RealRangeListConstraint ret_val
;
437 ret_val
.has_nan
= !has_nan
;
441 string
RealRangeListConstraint::to_string() const
445 ret_val
+= rlc
.to_string(false);
447 if (rlc
.is_empty()!=TTRUE
) ret_val
+= ',';
454 bool RealRangeListConstraint::is_upper_limit_infinity () const
456 return rlc
.is_upper_limit_infinity();
459 bool RealRangeListConstraint::is_lower_limit_infinity () const
461 return rlc
.is_lower_limit_infinity();
464 ////////////////////////////////////////////////////////////////////////////////
466 string
BooleanListConstraint::to_string() const
470 if (values
&BC_FALSE
) ret_val
+= "false";
471 if (values
==BC_ALL
) ret_val
+= ',';
472 if (values
&BC_TRUE
) ret_val
+= "true";
477 ////////////////////////////////////////////////////////////////////////////////
479 string
VerdicttypeListConstraint::to_string() const
481 static const size_t verdict_count
= 5;
482 static const char* verdict_names
[verdict_count
] = { "none", "pass", "inconc", "fail", "error" };
485 bool has_value
= false;
486 for (size_t i
=VC_NONE
,idx
=0; (i
<VC_ALL
)&&(idx
<verdict_count
); i
<<=1,idx
++)
489 if (has_value
) ret_val
+= ',';
490 ret_val
+= verdict_names
[idx
];
498 ////////////////////////////////////////////////////////////////////////////////
500 tribool
StringPatternConstraint::match(const string
& str
) const
502 string patt
= pattern
->get_full_str();
503 if (patt
.size()==0) return TRIBOOL(str
.size()==0);
504 string
*result
= regexp(str
, string('(')+patt
+string(')'), 0);
505 bool rv
= (result
->size()!=0);
510 string
StringPatternConstraint::to_string() const
513 ret_val
+= "pattern(";
514 ret_val
+= pattern
->get_full_str();
519 ////////////////////////////////////////////////////////////////////////////////
520 // constraint classes for structured types
522 void ValueList::clean_up()
527 void ValueList::copy_content(const ValueList
& other
)
529 for (size_t j
=0; j
<other
.values
.size(); j
++) values
.add(other
.values
[j
]);
532 tribool
ValueList::is_equal(const ValueList
& other
) const
534 if (values
.size()!=other
.values
.size()) return TFALSE
;
535 dynamic_array
<bool> found(other
.values
.size()); // helper to skip unnecessary comparisons
536 for (size_t j
=0; j
<other
.values
.size(); j
++) found
[j
] = false;
537 for (size_t i
=0; i
<values
.size(); i
++) {
538 bool found_i
= false;
539 for (size_t j
=0; j
<other
.values
.size(); j
++) {
540 if (found
[j
]) continue; // skip already found equal elements
541 if ( (values
[i
]==other
.values
[j
]) || (*(values
[i
])==*(other
.values
[j
])) ) {
547 if (!found_i
) return TFALSE
;
552 bool ValueList::is_element(Value
* v
) const
554 for (size_t i
=0; i
<values
.size(); i
++) {
555 if ( (values
[i
]==v
) || (*(values
[i
])==*v
) ) return true;
560 ValueList
ValueList::set_operation(const ValueList
& other
, bool is_union
) const
564 for (size_t i
=0; i
<values
.size(); i
++) ret_val
.values
.add(values
[i
]);
565 for (size_t i
=0; i
<other
.values
.size(); i
++) {
566 if (!is_element(other
.values
[i
])) ret_val
.values
.add(other
.values
[i
]);
569 for (size_t i
=0; i
<values
.size(); i
++) {
570 if (other
.is_element(values
[i
])) ret_val
.values
.add(values
[i
]);
576 ValueList
ValueList::operator-(const ValueList
& other
) const
579 for (size_t i
=0; i
<values
.size(); i
++) {
580 if (!other
.is_element(values
[i
])) ret_val
.values
.add(values
[i
]);
585 void ValueList::remove(const SizeRangeListConstraint
& size_constraint
, bool if_element
)
587 for (size_t i
=0; i
<values
.size(); i
++) {
588 if (size_constraint
.is_element(size_limit_t(values
[i
]->get_nof_comps()))==if_element
) {
595 string
ValueList::to_string() const
599 for (size_t i
=0; i
<values
.size(); i
++) {
600 if (i
>0) ret_val
+= ',';
601 ret_val
+= values
[i
]->create_stringRepr();
607 ////////////////////////////////////////////////////////////////////////////////
609 tribool
ValueListConstraint::is_empty() const
611 return complemented
? values
.is_full() : values
.is_empty();
615 tribool
ValueListConstraint::is_full() const
617 return complemented
? values
.is_empty() : values
.is_full();
621 tribool
ValueListConstraint::is_equal(const ValueListConstraint
& other
) const
623 return (complemented
==other
.complemented
) ? values
.is_equal(other
.values
) : TUNKNOWN
;
627 bool ValueListConstraint::is_element(Value
* v
) const
629 return complemented
^ values
.is_element(v
);
632 ValueListConstraint
ValueListConstraint::operator+(const ValueListConstraint
& other
) const
634 ValueListConstraint ret_val
;
636 if (other
.complemented
) {
637 ret_val
.complemented
= true;
638 ret_val
.values
= values
* other
.values
;
640 ret_val
.complemented
= true;
641 ret_val
.values
= values
- other
.values
;
644 if (other
.complemented
) {
645 ret_val
.complemented
= true;
646 ret_val
.values
= other
.values
- values
;
648 ret_val
.complemented
= false;
649 ret_val
.values
= values
+ other
.values
;
655 ValueListConstraint
ValueListConstraint::operator*(const ValueListConstraint
& other
) const
657 ValueListConstraint ret_val
;
659 if (other
.complemented
) {
660 ret_val
.complemented
= true;
661 ret_val
.values
= values
+ other
.values
;
663 ret_val
.complemented
= false;
664 ret_val
.values
= other
.values
- values
;
667 if (other
.complemented
) {
668 ret_val
.complemented
= false;
669 ret_val
.values
= values
- other
.values
;
671 ret_val
.complemented
= false;
672 ret_val
.values
= values
* other
.values
;
678 ValueListConstraint
ValueListConstraint::operator~() const
680 ValueListConstraint ret_val
;
681 ret_val
.complemented
= !complemented
;
682 ret_val
.values
= values
;
686 string
ValueListConstraint::to_string() const
690 ret_val
+= "(ALL except ";
691 ret_val
+= values
.to_string();
695 return values
.to_string();
698 ////////////////////////////////////////////////////////////////////////////////
700 tribool
RecofConstraint::is_empty() const
702 if ( (size_constraint
.is_empty()==TTRUE
) && (has_values
.is_empty()==TTRUE
) ) return TTRUE
;
703 if (has_values
.is_empty()==TFALSE
) return TFALSE
;
704 if (not_values
.is_empty()==TTRUE
) return TFALSE
;
705 return TUNKNOWN
; // the set of not_values may possibly cancel the size constraint set
708 tribool
RecofConstraint::is_full() const
710 if ( (size_constraint
.is_full()==TTRUE
) && (not_values
.is_empty()==TTRUE
) ) return TTRUE
;
711 if (not_values
.is_empty()==TFALSE
) return TFALSE
;
715 tribool
RecofConstraint::is_equal(const RecofConstraint
& other
) const
717 if ( (size_constraint
.is_equal(other
.size_constraint
)==TTRUE
) &&
718 (has_values
.is_equal(other
.has_values
)==TTRUE
) && (not_values
.is_equal(other
.not_values
)==TTRUE
) )
720 return TUNKNOWN
; // unknown because there's no canonical form
723 bool RecofConstraint::is_element(Value
* v
) const
725 if (size_constraint
.is_element(size_limit_t(v
->get_nof_comps()))) return !not_values
.is_element(v
);
726 return has_values
.is_element(v
);
729 // representation of two sets: [Si+Vi-Ni] where Si=size_constraint, Vi=has_values, Ni=not_values
730 // UNION: [S1+V1-N1] + [S2+V2-N2] = ... = [(S1+S2)+(V1+V2)-((~S1*N2)+(N1*~S2)+(N1*N2))]
731 // INTERSECTION: [S1+V1-N1] * [S2+V2-N2] = ... = [(S1*S2)+((S1*V2-N1)+(S2*V1-N2)+(V1*V2))-(N1+N2)]
732 RecofConstraint
RecofConstraint::set_operation(const RecofConstraint
& other
, bool is_union
) const
734 RecofConstraint ret_val
;
735 ret_val
.size_constraint
= size_constraint
.set_operation(other
.size_constraint
, is_union
);
738 ret_val
.has_values
= has_values
+ other
.has_values
;
740 ValueList vlc1
= other
.not_values
;
741 vlc1
.remove(size_constraint
, true);
743 ValueList vlc2
= not_values
;
744 vlc2
.remove(other
.size_constraint
, true);
745 // ((~S1*N2)+(N1*~S2)+(N1*N2))
746 ret_val
.not_values
= vlc1
+ vlc2
+ (not_values
* other
.not_values
);
747 } else { // intersection
749 ValueList vlc1
= has_values
;
750 vlc1
.remove(other
.size_constraint
, false);
751 vlc1
= vlc1
- other
.not_values
;
753 ValueList vlc2
= other
.has_values
;
754 vlc2
.remove(size_constraint
, false);
755 vlc2
= vlc2
- not_values
;
756 // (S1*V2-N1)+(S2*V1-N2)+(V1*V2)
757 ret_val
.has_values
= (has_values
* other
.has_values
) + vlc1
+ vlc2
;
758 // union of not_values
759 ret_val
.not_values
= not_values
+ other
.not_values
;
761 // drop the intersection, holes and points cancel each other
762 ValueList vlc
= ret_val
.has_values
* ret_val
.not_values
;
763 ret_val
.has_values
= ret_val
.has_values
- vlc
;
764 ret_val
.not_values
= ret_val
.not_values
- vlc
;
765 // drop ret_val.has_values elements that are elements of the ret_val.size_constraint set
766 ret_val
.has_values
.remove(ret_val
.size_constraint
, true);
767 // drop ret_val.not_values elements that are not elements of the ret_val.size_constraint set
768 ret_val
.not_values
.remove(ret_val
.size_constraint
, false);
772 RecofConstraint
RecofConstraint::operator~() const
774 RecofConstraint ret_val
;
775 ret_val
.size_constraint
= ~size_constraint
;
776 ret_val
.has_values
= not_values
;
777 ret_val
.not_values
= has_values
;
781 tribool
RecofConstraint::get_size_limit(bool is_upper
, size_limit_t
& limit
) const
783 if (size_constraint
.is_empty()==TTRUE
) return TFALSE
;
784 limit
= is_upper
? size_constraint
.get_maximal() : size_constraint
.get_minimal();
788 string
RecofConstraint::to_string() const
791 if (has_values
.is_empty()!=TTRUE
) ret_val
+= has_values
.to_string();
792 if (size_constraint
.is_empty()!=TTRUE
) {
793 if (has_values
.is_empty()!=TTRUE
) ret_val
+= " union ";
795 ret_val
+= size_constraint
.to_string();
798 if (not_values
.is_empty()!=TTRUE
) {
799 ret_val
+= " except ";
800 ret_val
+= not_values
.to_string();
806 } // namespace Common