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
15 * Szabo, Janos Zoltan – initial implementation
18 ******************************************************************************/
21 #include "../common/memory.h"
22 #include "Template.hh"
26 #include "Param_Types.hh"
28 #ifdef TITAN_RUNTIME_2
31 void Base_Template::check_restriction(template_res t_res
, const char* t_name
,
32 boolean legacy
/* = FALSE */) const
34 if (template_selection
==UNINITIALIZED_TEMPLATE
) return;
35 switch ((t_name
&&(t_res
==TR_VALUE
))?TR_OMIT
:t_res
) {
37 if (!is_ifpresent
&& template_selection
==SPECIFIC_VALUE
) return;
40 if (!is_ifpresent
&& (template_selection
==OMIT_VALUE
||
41 template_selection
==SPECIFIC_VALUE
)) return;
44 if (!match_omit(legacy
)) return;
49 TTCN_error("Restriction `%s' on template of type %s violated.",
50 get_res_name(t_res
), t_name
? t_name
: get_descriptor()->name
);
54 Base_Template::Base_Template()
55 : template_selection(UNINITIALIZED_TEMPLATE
), is_ifpresent(FALSE
)
58 Base_Template::Base_Template(template_sel other_value
)
59 : template_selection(other_value
), is_ifpresent(FALSE
)
62 void Base_Template::check_single_selection(template_sel other_value
)
64 switch (other_value
) {
70 TTCN_error("Initialization of a template with an invalid selection.");
74 void Base_Template::set_selection(template_sel other_value
)
76 template_selection
= other_value
;
80 void Base_Template::set_selection(const Base_Template
& other_value
)
82 template_selection
= other_value
.template_selection
;
83 is_ifpresent
= other_value
.is_ifpresent
;
86 void Base_Template::log_generic() const
88 switch (template_selection
) {
89 case UNINITIALIZED_TEMPLATE
:
90 TTCN_Logger::log_event_uninitialized();
93 TTCN_Logger::log_event_str("omit");
96 TTCN_Logger::log_char('?');
99 TTCN_Logger::log_char('*');
102 TTCN_Logger::log_event_str("<unknown template selection>");
107 void Base_Template::log_ifpresent() const
109 if (is_ifpresent
) TTCN_Logger::log_event_str(" ifpresent");
112 void Base_Template::encode_text_base(Text_Buf
& text_buf
) const
114 text_buf
.push_int(template_selection
);
115 text_buf
.push_int(is_ifpresent
);
118 void Base_Template::decode_text_base(Text_Buf
& text_buf
)
120 template_selection
= (template_sel
)text_buf
.pull_int().get_val();
121 is_ifpresent
= (boolean
)text_buf
.pull_int().get_val();
124 void Base_Template::set_ifpresent()
129 boolean
Base_Template::is_omit() const
131 return template_selection
== OMIT_VALUE
&& !is_ifpresent
;
134 boolean
Base_Template::is_any_or_omit() const
136 return template_selection
== ANY_OR_OMIT
&& !is_ifpresent
;
139 const char* Base_Template::get_res_name(template_res tr
)
142 case TR_VALUE
: return "value";
143 case TR_OMIT
: return "omit";
144 case TR_PRESENT
: return "present";
147 return "<unknown/invalid>";
150 void Base_Template::set_param(Module_Param
& /*param*/)
152 TTCN_error("Internal error: Base_Template::set_param()");
155 Module_Param
* Base_Template::get_param(Module_Param_Name
& /* param_name */) const
157 TTCN_error("Internal error: Base_Template::get_param()");
161 Restricted_Length_Template::Restricted_Length_Template()
163 length_restriction_type
= NO_LENGTH_RESTRICTION
;
166 Restricted_Length_Template::Restricted_Length_Template(template_sel other_value
)
167 : Base_Template(other_value
)
169 length_restriction_type
= NO_LENGTH_RESTRICTION
;
172 void Restricted_Length_Template::set_selection(template_sel other_value
)
174 template_selection
= other_value
;
175 is_ifpresent
= FALSE
;
176 length_restriction_type
= NO_LENGTH_RESTRICTION
;
179 void Restricted_Length_Template::set_selection
180 (const Restricted_Length_Template
& other_value
)
182 template_selection
= other_value
.template_selection
;
183 is_ifpresent
= other_value
.is_ifpresent
;
184 length_restriction_type
= other_value
.length_restriction_type
;
185 length_restriction
= other_value
.length_restriction
;
188 boolean
Restricted_Length_Template::match_length(int value_length
) const
190 switch (length_restriction_type
) {
191 case NO_LENGTH_RESTRICTION
:
193 case SINGLE_LENGTH_RESTRICTION
:
194 return value_length
== length_restriction
.single_length
;
195 case RANGE_LENGTH_RESTRICTION
:
196 return value_length
>= length_restriction
.range_length
.min_length
&&
197 (!length_restriction
.range_length
.max_length_set
||
198 value_length
<= length_restriction
.range_length
.max_length
);
200 TTCN_error("Internal error: Matching with a template that has invalid "
201 "length restriction type.");
206 int Restricted_Length_Template::check_section_is_single(int min_size
,
207 boolean has_any_or_none
, const char* operation_name
,
208 const char* type_name_prefix
, const char* type_name
) const
210 if (has_any_or_none
) // upper limit is infinity
212 switch (length_restriction_type
)
214 case NO_LENGTH_RESTRICTION
:
215 TTCN_error("Performing %sof() operation on %s %s with no exact %s.",
216 operation_name
, type_name_prefix
, type_name
, operation_name
);
217 case SINGLE_LENGTH_RESTRICTION
:
218 if (length_restriction
.single_length
>=min_size
)
219 return length_restriction
.single_length
;
220 TTCN_error("Performing %sof() operation on an invalid %s. "
221 "The minimum %s (%d) contradicts the "
222 "length restriction (%d).",
223 operation_name
, type_name
, operation_name
,
224 min_size
, length_restriction
.single_length
);
225 case RANGE_LENGTH_RESTRICTION
: {
226 boolean has_invalid_restriction
;
227 if (match_length(min_size
))
229 if (length_restriction
.range_length
.max_length_set
&&
230 (min_size
==length_restriction
.range_length
.max_length
))
232 has_invalid_restriction
= FALSE
;
236 has_invalid_restriction
=
237 min_size
>length_restriction
.range_length
.min_length
;
239 if (has_invalid_restriction
)
241 if (length_restriction
.range_length
.max_length_set
)
242 TTCN_error("Performing %sof() operation on an invalid %s. "
243 "The minimum %s (%d) contradicts the "
244 "length restriction (%d..%d).",
245 operation_name
, type_name
, operation_name
, min_size
,
246 length_restriction
.range_length
.min_length
,
247 length_restriction
.range_length
.max_length
);
249 TTCN_error("Performing %sof() operation on an invalid %s. "
250 "The minimum %s (%d) contradicts the "
251 "length restriction (%d..infinity).",
252 operation_name
, type_name
, operation_name
, min_size
,
253 length_restriction
.range_length
.min_length
);
256 TTCN_error("Performing %sof() operation on %s %s with no exact %s.",
257 operation_name
, type_name_prefix
, type_name
, operation_name
);
261 TTCN_error("Internal error: Template has invalid "
262 "length restriction type.");
265 else // exact size is in min_size, check for invalid restriction
267 switch (length_restriction_type
)
269 case NO_LENGTH_RESTRICTION
:
271 case SINGLE_LENGTH_RESTRICTION
:
272 if (length_restriction
.single_length
==min_size
) return min_size
;
273 TTCN_error("Performing %sof() operation on an invalid %s. "
274 "The %s (%d) contradicts the length restriction (%d).",
275 operation_name
, type_name
, operation_name
, min_size
,
276 length_restriction
.single_length
);
277 case RANGE_LENGTH_RESTRICTION
:
278 if (!match_length(min_size
))
280 if (length_restriction
.range_length
.max_length_set
)
281 TTCN_error("Performing %sof() operation on an invalid %s. "
282 "The %s (%d) contradicts the length restriction (%d..%d).",
283 operation_name
, type_name
, operation_name
, min_size
,
284 length_restriction
.range_length
.min_length
,
285 length_restriction
.range_length
.max_length
);
287 TTCN_error("Performing %sof() operation on an invalid %s. "
288 "The %s (%d) contradicts the "
289 "length restriction (%d..infinity).",
290 operation_name
, type_name
, operation_name
, min_size
,
291 length_restriction
.range_length
.min_length
);
296 TTCN_error("Internal error: Template has invalid "
297 "length restriction type.");
303 void Restricted_Length_Template::log_restricted() const
305 switch (length_restriction_type
) {
306 case SINGLE_LENGTH_RESTRICTION
:
307 TTCN_Logger::log_event(" length (%d)",
308 length_restriction
.single_length
);
310 case NO_LENGTH_RESTRICTION
:
312 case RANGE_LENGTH_RESTRICTION
:
313 TTCN_Logger::log_event(" length (%d .. ",
314 length_restriction
.range_length
.min_length
);
315 if (length_restriction
.range_length
.max_length_set
)
316 TTCN_Logger::log_event("%d)",
317 length_restriction
.range_length
.max_length
);
318 else TTCN_Logger::log_event_str("infinity)");
321 TTCN_Logger::log_event_str("<unknown length restriction>");
326 void Restricted_Length_Template::log_match_length(int value_length
) const
328 if (length_restriction_type
!= NO_LENGTH_RESTRICTION
) {
329 if(TTCN_Logger::VERBOSITY_COMPACT
== TTCN_Logger::get_matching_verbosity()){
330 if (!match_length(value_length
)){
331 TTCN_Logger::print_logmatch_buffer();
333 TTCN_Logger::log_event(" with %d ", value_length
);
337 TTCN_Logger::log_event(" with %d ", value_length
);
338 if (match_length(value_length
)) TTCN_Logger::log_event_str("matched");
339 else TTCN_Logger::log_event_str("unmatched");
344 void Restricted_Length_Template::encode_text_restricted(Text_Buf
& text_buf
)const
346 encode_text_base(text_buf
);
347 text_buf
.push_int(length_restriction_type
);
348 switch (length_restriction_type
) {
349 case SINGLE_LENGTH_RESTRICTION
:
350 text_buf
.push_int(length_restriction
.single_length
);
352 case NO_LENGTH_RESTRICTION
:
354 case RANGE_LENGTH_RESTRICTION
:
355 text_buf
.push_int(length_restriction
.range_length
.min_length
);
356 text_buf
.push_int(length_restriction
.range_length
.max_length_set
);
357 if (length_restriction
.range_length
.max_length_set
)
358 text_buf
.push_int(length_restriction
.range_length
.max_length
);
361 TTCN_error("Text encoder: encoding an unknown/unsupported length "
362 "restriction type in a template.");
366 void Restricted_Length_Template::decode_text_restricted(Text_Buf
& text_buf
)
368 decode_text_base(text_buf
);
369 length_restriction_type
= (length_restriction_type_t
)
370 text_buf
.pull_int().get_val();
371 switch (length_restriction_type
) {
372 case SINGLE_LENGTH_RESTRICTION
:
373 length_restriction
.single_length
= text_buf
.pull_int().get_val();
375 case NO_LENGTH_RESTRICTION
:
377 case RANGE_LENGTH_RESTRICTION
:
378 length_restriction
.range_length
.min_length
=
379 text_buf
.pull_int().get_val();
380 length_restriction
.range_length
.max_length_set
=
381 (boolean
)text_buf
.pull_int().get_val();
382 if (length_restriction
.range_length
.max_length_set
)
383 length_restriction
.range_length
.max_length
=
384 text_buf
.pull_int().get_val();
387 TTCN_error("Text decoder: an unknown/unsupported length restriction "
388 "type was received for a template.");
392 void Restricted_Length_Template::set_length_range(const Module_Param
& param
)
394 Module_Param_Length_Restriction
* length_range
= param
.get_length_restriction();
395 if (length_range
==NULL
) {
396 length_restriction_type
= NO_LENGTH_RESTRICTION
;
399 if (length_range
->is_single()) {
400 length_restriction_type
= SINGLE_LENGTH_RESTRICTION
;
401 length_restriction
.single_length
= (int)(length_range
->get_min());
403 length_restriction_type
= RANGE_LENGTH_RESTRICTION
;
404 length_restriction
.range_length
.min_length
= (int)(length_range
->get_min());
405 length_restriction
.range_length
.max_length_set
= length_range
->get_has_max();
406 if (length_restriction
.range_length
.max_length_set
) {
407 length_restriction
.range_length
.max_length
= (int)(length_range
->get_max());
412 Module_Param_Length_Restriction
* Restricted_Length_Template::get_length_range() const
414 if (length_restriction_type
== NO_LENGTH_RESTRICTION
) {
417 Module_Param_Length_Restriction
* mp_res
= new Module_Param_Length_Restriction();
418 if (length_restriction_type
== SINGLE_LENGTH_RESTRICTION
) {
419 mp_res
->set_single(length_restriction
.single_length
);
422 mp_res
->set_min(length_restriction
.range_length
.min_length
);
423 if (length_restriction
.range_length
.max_length_set
) {
424 mp_res
->set_max(length_restriction
.range_length
.max_length
);
430 void Restricted_Length_Template::set_single_length(int single_length
)
432 length_restriction_type
= SINGLE_LENGTH_RESTRICTION
;
433 length_restriction
.single_length
= single_length
;
436 void Restricted_Length_Template::set_min_length(int min_length
)
438 if (min_length
< 0) TTCN_error("The lower limit for the length is negative"
439 " (%d) in a template with length restriction.", min_length
);
440 length_restriction_type
= RANGE_LENGTH_RESTRICTION
;
441 length_restriction
.range_length
.min_length
= min_length
;
442 length_restriction
.range_length
.max_length_set
= FALSE
;
445 void Restricted_Length_Template::set_max_length(int max_length
)
447 if (length_restriction_type
!= RANGE_LENGTH_RESTRICTION
)
448 TTCN_error("Internal error: Setting a maximum length for a template "
449 "the length restriction of which is not a range.");
450 if (max_length
< 0) TTCN_error("The upper limit for the length is negative"
451 " (%d) in a template with length restriction.", max_length
);
452 if (length_restriction
.range_length
.min_length
> max_length
)
453 TTCN_error("The upper limit for the length (%d) is smaller than the "
454 "lower limit (%d) in a template with length restriction.",
455 max_length
, length_restriction
.range_length
.min_length
);
456 length_restriction
.range_length
.max_length
= max_length
;
457 length_restriction
.range_length
.max_length_set
= TRUE
;
460 boolean
Restricted_Length_Template::is_omit() const
462 return template_selection
== OMIT_VALUE
&& !is_ifpresent
&&
463 length_restriction_type
== NO_LENGTH_RESTRICTION
;
466 boolean
Restricted_Length_Template::is_any_or_omit() const
468 return template_selection
== ANY_OR_OMIT
&& !is_ifpresent
&&
469 length_restriction_type
== NO_LENGTH_RESTRICTION
;
472 ////////////////////////////////////////////////////////////////////////////////
474 struct Record_Of_Template::Pair_of_elements
{
475 unsigned int start_index
, end_index
; //beginning and ending index
478 Record_Of_Template::Record_Of_Template()
480 #ifdef TITAN_RUNTIME_2
483 number_of_permutations
= 0;
484 permutation_intervals
= NULL
;
487 Record_Of_Template::Record_Of_Template(template_sel other_value
)
488 : Restricted_Length_Template(other_value
)
490 #ifdef TITAN_RUNTIME_2
493 number_of_permutations
= 0;
494 permutation_intervals
= NULL
;
497 void Record_Of_Template::clean_up_intervals()
499 number_of_permutations
= 0;
500 Free(permutation_intervals
);
501 permutation_intervals
= NULL
;
504 void Record_Of_Template::set_selection(template_sel other_value
)
506 Restricted_Length_Template::set_selection(other_value
);
507 clean_up_intervals();
510 void Record_Of_Template::set_selection(const Record_Of_Template
& other_value
)
512 Restricted_Length_Template::set_selection(other_value
);
513 clean_up_intervals();
514 if(other_value
.template_selection
== SPECIFIC_VALUE
)
516 number_of_permutations
= other_value
.number_of_permutations
;
517 permutation_intervals
= (Pair_of_elements
*) Malloc(number_of_permutations
* sizeof(Pair_of_elements
));
518 memcpy(permutation_intervals
,other_value
.permutation_intervals
,number_of_permutations
*sizeof(Pair_of_elements
));
522 #ifdef TITAN_RUNTIME_2
524 boolean
Record_Of_Template::match_function_specific(
525 const Base_Type
*value_ptr
, int value_index
,
526 const Restricted_Length_Template
*template_ptr
, int template_index
,
529 const Record_Of_Template
* rec_tmpl_ptr
= static_cast<const Record_Of_Template
*>(template_ptr
);
530 if (value_index
>= 0) {
531 const Record_Of_Type
* recof_ptr
= static_cast<const Record_Of_Type
*>(value_ptr
);
532 return rec_tmpl_ptr
->single_value
.value_elements
[template_index
]->matchv(recof_ptr
->get_at(value_index
), legacy
);
534 return rec_tmpl_ptr
->single_value
.value_elements
[template_index
]->is_any_or_omit();
538 void Record_Of_Template::valueofv(Base_Type
* value
) const
540 if (template_selection
!= SPECIFIC_VALUE
|| is_ifpresent
)
541 TTCN_error("Performing a valueof or send operation on a non-specific template of type %s.", get_descriptor()->name
);
542 Record_Of_Type
* recof_value
= static_cast<Record_Of_Type
*>(value
);
543 recof_value
->set_size(single_value
.n_elements
);
544 for (int elem_count
= 0; elem_count
< single_value
.n_elements
; elem_count
++)
545 single_value
.value_elements
[elem_count
]->valueofv(recof_value
->get_at(elem_count
));
546 recof_value
->set_err_descr(err_descr
);
549 void Record_Of_Template::set_value(template_sel other_value
)
551 check_single_selection(other_value
);
553 set_selection(other_value
);
557 void Record_Of_Template::clean_up()
559 switch (template_selection
) {
561 for (int elem_count
= 0; elem_count
< single_value
.n_elements
; elem_count
++)
562 delete single_value
.value_elements
[elem_count
];
563 free_pointers((void**)single_value
.value_elements
);
566 case COMPLEMENTED_LIST
:
567 for (int list_count
= 0; list_count
< value_list
.n_values
; list_count
++)
568 delete value_list
.list_value
[list_count
];
569 free_pointers((void**)value_list
.list_value
);
574 template_selection
= UNINITIALIZED_TEMPLATE
;
577 void Record_Of_Template::copy_value(const Base_Type
* other_value
)
579 if (!other_value
->is_bound())
580 TTCN_error("Initialization of a record of template with an unbound value.");
581 const Record_Of_Type
* other_recof
= static_cast<const Record_Of_Type
*>(other_value
);
582 single_value
.n_elements
= other_recof
->size_of();
583 single_value
.value_elements
= (Base_Template
**)allocate_pointers(single_value
.n_elements
);
584 for (int elem_count
= 0; elem_count
< single_value
.n_elements
; elem_count
++) {
585 single_value
.value_elements
[elem_count
] = create_elem();
586 if (other_recof
->get_at(elem_count
)->is_bound()) {
587 single_value
.value_elements
[elem_count
]->copy_value(other_recof
->get_at(elem_count
));
590 set_selection(SPECIFIC_VALUE
);
591 err_descr
= other_recof
->get_err_descr();
594 void Record_Of_Template::copy_template(const Record_Of_Template
& other_value
)
596 switch (other_value
.template_selection
) {
598 single_value
.n_elements
= other_value
.single_value
.n_elements
;
599 single_value
.value_elements
= (Base_Template
**)allocate_pointers(single_value
.n_elements
);
600 for (int elem_count
= 0; elem_count
< single_value
.n_elements
; elem_count
++) {
601 if (other_value
.single_value
.value_elements
[elem_count
]->is_bound()) {
602 single_value
.value_elements
[elem_count
] = other_value
.single_value
.value_elements
[elem_count
]->clone();
604 single_value
.value_elements
[elem_count
] = create_elem();
613 case COMPLEMENTED_LIST
:
614 value_list
.n_values
= other_value
.value_list
.n_values
;
615 value_list
.list_value
= (Record_Of_Template
**)allocate_pointers(value_list
.n_values
);
616 for (int list_count
= 0; list_count
< value_list
.n_values
; list_count
++) {
617 if (other_value
.value_list
.list_value
[list_count
]->is_bound()) {
618 value_list
.list_value
[list_count
] = static_cast<Record_Of_Template
*>(other_value
.value_list
.list_value
[list_count
]->clone());
620 value_list
.list_value
[list_count
] = static_cast<Record_Of_Template
*>(create_elem());
625 TTCN_error("Copying an uninitialized/unsupported record of template.");
628 set_selection(other_value
);
629 err_descr
= other_value
.err_descr
;
632 void Record_Of_Template::copy_optional(const Base_Type
* other_value
)
634 if (other_value
->is_present()) {
635 const Record_Of_Type
* other_recof
= static_cast<const Record_Of_Type
*>(other_value
->get_opt_value());
636 copy_value(other_recof
);
637 } else if (other_value
->is_bound()) {
638 set_selection(OMIT_VALUE
);
641 TTCN_error("Initialization of a record of template with an unbound optional field.");
645 Base_Template
* Record_Of_Template::clone() const
647 Record_Of_Template
* recof
= create();
648 recof
->copy_template(*this);
652 Record_Of_Template::~Record_Of_Template()
654 clean_up_intervals();
658 Record_Of_Template::~Record_Of_Template()
660 clean_up_intervals();
664 void Record_Of_Template::encode_text_permutation(Text_Buf
& text_buf
) const
666 encode_text_restricted(text_buf
);
667 text_buf
.push_int(number_of_permutations
);
669 for(unsigned int i
= 0; i
< number_of_permutations
; i
++)
671 text_buf
.push_int(permutation_intervals
[i
].start_index
);
672 text_buf
.push_int(permutation_intervals
[i
].end_index
);
676 void Record_Of_Template::decode_text_permutation(Text_Buf
& text_buf
)
678 decode_text_restricted(text_buf
);
680 number_of_permutations
= text_buf
.pull_int().get_val();
681 permutation_intervals
= (Pair_of_elements
*)Malloc
682 (number_of_permutations
* sizeof(Pair_of_elements
));
684 for (unsigned int i
= 0; i
< number_of_permutations
; i
++)
686 permutation_intervals
[i
].start_index
=
687 text_buf
.pull_int().get_val();
688 permutation_intervals
[i
].end_index
=
689 text_buf
.pull_int().get_val();
693 void Record_Of_Template::add_permutation(unsigned int start_index
, unsigned int end_index
)
695 if(start_index
> end_index
)
696 TTCN_error("wrong permutation interval settings start (%d)"
697 "can not be greater than end (%d)",start_index
, end_index
);
699 if(number_of_permutations
> 0 &&
700 permutation_intervals
[number_of_permutations
- 1].end_index
>= start_index
)
701 TTCN_error("the %dth permutation overlaps the previous one", number_of_permutations
);
703 permutation_intervals
= (Pair_of_elements
*)Realloc(permutation_intervals
, (number_of_permutations
+ 1) * sizeof(Pair_of_elements
));
704 permutation_intervals
[number_of_permutations
].start_index
= start_index
;
705 permutation_intervals
[number_of_permutations
].end_index
= end_index
;
706 number_of_permutations
++;
709 unsigned int Record_Of_Template::get_number_of_permutations(void) const
711 return number_of_permutations
;
714 unsigned int Record_Of_Template::get_permutation_start(unsigned int index_value
) const
716 if(index_value
>= number_of_permutations
)
717 TTCN_error("Index overflow (%d)", index_value
);
719 return permutation_intervals
[index_value
].start_index
;
722 unsigned int Record_Of_Template::get_permutation_end(unsigned int index_value
) const
724 if(index_value
>= number_of_permutations
)
725 TTCN_error("Index overflow (%d)", index_value
);
727 return permutation_intervals
[index_value
].end_index
;
730 unsigned int Record_Of_Template::get_permutation_size(unsigned int index_value
) const
732 if(index_value
>= number_of_permutations
)
733 TTCN_error("Index overflow (%d)", index_value
);
735 return permutation_intervals
[index_value
].end_index
- permutation_intervals
[index_value
].start_index
+ 1;
738 boolean
Record_Of_Template::permutation_starts_at(unsigned int index_value
) const
740 for(unsigned int i
= 0; i
< number_of_permutations
; i
++)
742 if(permutation_intervals
[i
].start_index
== index_value
)
749 boolean
Record_Of_Template::permutation_ends_at(unsigned int index_value
) const
751 for(unsigned int i
= 0; i
< number_of_permutations
; i
++)
753 if(permutation_intervals
[i
].end_index
== index_value
)
760 #ifdef TITAN_RUNTIME_2
762 void Record_Of_Template::substr_(int index
, int returncount
, Record_Of_Type
* rec_of
) const
764 if (!is_value()) TTCN_error("The first argument of function substr() is a template of type %s with non-specific value.", get_descriptor()->name
);
765 rec_of
->set_val(NULL_VALUE
);
766 Base_Type
* this_value
= rec_of
->clone();
767 valueofv(this_value
);
768 static_cast<Record_Of_Type
*>(this_value
)->substr_(index
, returncount
, rec_of
);
772 void Record_Of_Template::replace_(int index
, int len
,
773 const Record_Of_Template
* repl
, Record_Of_Type
* rec_of
) const
775 if (!is_value()) TTCN_error("The first argument of function replace() is a template of type %s with non-specific value.", get_descriptor()->name
);
776 if (!repl
->is_value()) TTCN_error("The fourth argument of function replace() is a template of type %s with non-specific value.", repl
->get_descriptor()->name
);
777 rec_of
->set_val(NULL_VALUE
);
778 Base_Type
* this_value
= rec_of
->clone();
779 valueofv(this_value
);
780 Base_Type
* repl_value
= rec_of
->clone();
781 repl
->valueofv(repl_value
);
782 // call the replace() function of the value class instance
783 static_cast<Record_Of_Type
*>(this_value
)->replace_(index
, len
, static_cast<Record_Of_Type
*>(repl_value
), rec_of
);
788 void Record_Of_Template::replace_(int index
, int len
,
789 const Record_Of_Type
* repl
, Record_Of_Type
* rec_of
) const
791 if (!is_value()) TTCN_error("The first argument of function replace() is a template of type %s with non-specific value.", get_descriptor()->name
);
792 rec_of
->set_val(NULL_VALUE
);
793 Base_Type
* this_value
= rec_of
->clone();
794 valueofv(this_value
);
795 // call the replace() function of the value class instance
796 static_cast<Record_Of_Type
*>(this_value
)->replace_(index
, len
, repl
, rec_of
);
800 Base_Template
* Record_Of_Template::get_at(int index_value
)
803 TTCN_error("Accessing an element of a template for type %s using a "
804 "negative index: %d.", get_descriptor()->name
, index_value
);
805 switch (template_selection
) {
807 if(index_value
< single_value
.n_elements
) break;
812 case UNINITIALIZED_TEMPLATE
:
813 set_size(index_value
+ 1);
816 TTCN_error("Accessing an element of a non-specific template for type %s.",
817 get_descriptor()->name
);
820 return single_value
.value_elements
[index_value
];
823 Base_Template
* Record_Of_Template::get_at(const INTEGER
& index_value
)
825 if (!index_value
.is_bound())
826 TTCN_error("Using an unbound integer value for indexing a template of "
827 "type %s.", get_descriptor()->name
);
828 return get_at((int)index_value
);
831 const Base_Template
* Record_Of_Template::get_at(int index_value
) const
834 TTCN_error("Accessing an element of a template for type %s using "
835 "a negative index: %d.", get_descriptor()->name
, index_value
);
836 if (template_selection
!= SPECIFIC_VALUE
)
837 TTCN_error("Accessing an element of a non-specific template for type %s.",
838 get_descriptor()->name
);
839 if (index_value
>= single_value
.n_elements
)
840 TTCN_error("Index overflow in a template of type %s: The index is %d, but "
841 "the template has only %d elements.", get_descriptor()->name
, index_value
,
842 single_value
.n_elements
);
843 return single_value
.value_elements
[index_value
];
846 const Base_Template
* Record_Of_Template::get_at(
847 const INTEGER
& index_value
) const
849 if (!index_value
.is_bound())
850 TTCN_error("Using an unbound integer value for indexing a template of "
851 "type %s.", get_descriptor()->name
);
852 return get_at((int)index_value
);
855 void Record_Of_Template::set_size(int new_size
)
858 TTCN_error("Internal error: Setting a negative size for a template of "
859 "type %s.", get_descriptor()->name
);
860 template_sel old_selection
= template_selection
;
861 if (old_selection
!= SPECIFIC_VALUE
) {
863 set_selection(SPECIFIC_VALUE
);
864 single_value
.n_elements
= 0;
865 single_value
.value_elements
= NULL
;
867 if (new_size
> single_value
.n_elements
) {
868 single_value
.value_elements
= (Base_Template
**)reallocate_pointers(
869 (void**)single_value
.value_elements
, single_value
.n_elements
, new_size
);
870 if (old_selection
== ANY_VALUE
|| old_selection
== ANY_OR_OMIT
) {
871 for (int elem_count
= single_value
.n_elements
; elem_count
< new_size
; elem_count
++) {
872 single_value
.value_elements
[elem_count
] = create_elem();
873 single_value
.value_elements
[elem_count
]->set_value(ANY_VALUE
);
876 for (int elem_count
= single_value
.n_elements
; elem_count
< new_size
; elem_count
++)
877 single_value
.value_elements
[elem_count
] = create_elem();
879 single_value
.n_elements
= new_size
;
880 } else if (new_size
< single_value
.n_elements
) {
881 for (int elem_count
= new_size
; elem_count
< single_value
.n_elements
; elem_count
++)
882 delete single_value
.value_elements
[elem_count
];
883 single_value
.value_elements
= (Base_Template
**)reallocate_pointers(
884 (void**)single_value
.value_elements
, single_value
.n_elements
, new_size
);
885 single_value
.n_elements
= new_size
;
889 int Record_Of_Template::size_of(boolean is_size
) const
891 const char* op_name
= is_size
? "size" : "length";
893 boolean has_any_or_none
;
895 TTCN_error("Performing %sof() operation on a template of type %s "
896 "which has an ifpresent attribute.", op_name
, get_descriptor()->name
);
897 switch (template_selection
)
899 case SPECIFIC_VALUE
: {
901 has_any_or_none
= FALSE
;
902 int elem_count
= single_value
.n_elements
;
904 while (elem_count
>0 && !(single_value
.value_elements
[elem_count
-1])->is_bound())
907 for (int i
=0; i
<elem_count
; i
++)
909 switch (((Base_Template
*)single_value
.value_elements
[i
])->get_selection())
912 TTCN_error("Performing %sof() operation on a template of type %s "
913 "containing omit element.", op_name
, get_descriptor()->name
);
915 has_any_or_none
= TRUE
;
924 TTCN_error("Performing %sof() operation on a template of type %s"
925 " containing omit value.", op_name
, get_descriptor()->name
);
929 has_any_or_none
= TRUE
;
933 if (value_list
.n_values
<1)
934 TTCN_error("Performing %sof() operation on a template of type %s "
935 "containing an empty list.", op_name
, get_descriptor()->name
);
936 int item_size
= value_list
.list_value
[0]->size_of(is_size
);
937 for (int i
= 1; i
< value_list
.n_values
; i
++) {
938 if (value_list
.list_value
[i
]->size_of(is_size
)!=item_size
)
939 TTCN_error("Performing %sof() operation on a template of type %s "
940 "containing a value list with different sizes.", op_name
, get_descriptor()->name
);
942 min_size
= item_size
;
943 has_any_or_none
= FALSE
;
946 case COMPLEMENTED_LIST
:
947 TTCN_error("Performing %sof() operation on a template of type %s "
948 "containing complemented list.", op_name
, get_descriptor()->name
);
950 TTCN_error("Performing %sof() operation on an uninitialized/unsupported "
951 "template of type %s.", op_name
, get_descriptor()->name
);
953 return check_section_is_single(min_size
, has_any_or_none
, op_name
,
954 "a template of type", get_descriptor()->name
);
957 int Record_Of_Template::n_elem() const
959 switch (template_selection
) {
961 return single_value
.n_elements
;
963 case COMPLEMENTED_LIST
:
964 TTCN_error("Performing n_elem() operation on a template of type %s "
965 "containing complemented list.", get_descriptor()->name
);
967 case UNINITIALIZED_TEMPLATE
:
978 TTCN_error("Performing n_elem() operation on an uninitialized/unsupported "
979 "template of type %s.", get_descriptor()->name
);
982 boolean
Record_Of_Template::matchv(const Base_Type
* other_value
,
983 boolean legacy
) const
985 const Record_Of_Type
* other_recof
= static_cast<const Record_Of_Type
*>(other_value
);
986 if (!other_value
->is_bound()) return FALSE
;
987 int value_length
= other_recof
->size_of();
988 if (!match_length(value_length
)) return FALSE
;
989 switch (template_selection
) {
991 return match_record_of(other_recof
, value_length
, this,
992 single_value
.n_elements
, match_function_specific
, legacy
);
999 case COMPLEMENTED_LIST
:
1000 for (int list_count
= 0; list_count
< value_list
.n_values
; list_count
++)
1001 if (value_list
.list_value
[list_count
]->matchv(other_value
, legacy
))
1002 return template_selection
== VALUE_LIST
;
1003 return template_selection
== COMPLEMENTED_LIST
;
1005 TTCN_error("Matching with an uninitialized/unsupported template of type %s.",
1006 get_descriptor()->name
);
1011 boolean
Record_Of_Template::is_value() const
1013 if (template_selection
!= SPECIFIC_VALUE
|| is_ifpresent
) return FALSE
;
1014 for (int elem_count
= 0; elem_count
< single_value
.n_elements
; elem_count
++)
1015 if (!single_value
.value_elements
[elem_count
]->is_value()) return FALSE
;
1019 void Record_Of_Template::set_type(template_sel template_type
, int list_length
)
1022 switch (template_type
) {
1024 case COMPLEMENTED_LIST
:
1025 value_list
.n_values
= list_length
;
1026 value_list
.list_value
= (Record_Of_Template
**)allocate_pointers(value_list
.n_values
);
1027 for (int list_count
= 0; list_count
< value_list
.n_values
; list_count
++)
1028 value_list
.list_value
[list_count
] = create();
1031 TTCN_error("Internal error: Setting an invalid type for a template of "
1032 "type %s.", get_descriptor()->name
);
1034 set_selection(template_type
);
1037 Record_Of_Template
* Record_Of_Template::get_list_item(int list_index
)
1039 if (template_selection
!= VALUE_LIST
&& template_selection
!= COMPLEMENTED_LIST
)
1040 TTCN_error("Internal error: Accessing a list element of a non-list "
1041 "template of type %s.", get_descriptor()->name
);
1042 if (list_index
>= value_list
.n_values
|| list_index
< 0)
1043 TTCN_error("Internal error: Index overflow in a value list template "
1044 "of type %s.", get_descriptor()->name
);
1045 return value_list
.list_value
[list_index
];
1048 void Record_Of_Template::log() const
1050 switch (template_selection
) {
1051 case SPECIFIC_VALUE
:
1052 if (single_value
.n_elements
> 0) {
1053 TTCN_Logger::log_event_str("{ ");
1054 for (int elem_count
= 0; elem_count
< single_value
.n_elements
; elem_count
++) {
1055 if (elem_count
> 0) TTCN_Logger::log_event_str(", ");
1056 if (permutation_starts_at(elem_count
)) TTCN_Logger::log_event_str("permutation(");
1057 single_value
.value_elements
[elem_count
]->log();
1058 if (permutation_ends_at(elem_count
)) TTCN_Logger::log_char(')');
1060 TTCN_Logger::log_event_str(" }");
1061 } else TTCN_Logger::log_event_str("{ }");
1063 case COMPLEMENTED_LIST
:
1064 TTCN_Logger::log_event_str("complement ");
1067 TTCN_Logger::log_char('(');
1068 for (int list_count
= 0; list_count
< value_list
.n_values
; list_count
++) {
1069 if (list_count
> 0) TTCN_Logger::log_event_str(", ");
1070 value_list
.list_value
[list_count
]->log();
1072 TTCN_Logger::log_char(')');
1080 if (err_descr
) err_descr
->log();
1083 void Record_Of_Template::log_matchv(const Base_Type
* match_value
, boolean legacy
) const
1085 if (TTCN_Logger::VERBOSITY_COMPACT
== TTCN_Logger::get_matching_verbosity()) {
1086 if (matchv(match_value
, legacy
)) {
1087 TTCN_Logger::print_logmatch_buffer();
1088 TTCN_Logger::log_event_str(" matched");
1090 const Record_Of_Type
* recof_value
= static_cast<const Record_Of_Type
*>(match_value
);
1091 if (template_selection
== SPECIFIC_VALUE
&&
1092 single_value
.n_elements
> 0 && get_number_of_permutations() == 0 &&
1093 single_value
.n_elements
== recof_value
->size_of()) {
1094 size_t previous_size
= TTCN_Logger::get_logmatch_buffer_len();
1095 for (int elem_count
= 0; elem_count
< single_value
.n_elements
; elem_count
++) {
1096 if(!single_value
.value_elements
[elem_count
]->matchv(recof_value
->get_at(elem_count
), legacy
)){
1097 TTCN_Logger::log_logmatch_info("[%d]", elem_count
);
1098 single_value
.value_elements
[elem_count
]->log_matchv(recof_value
->get_at(elem_count
), legacy
);
1099 TTCN_Logger::set_logmatch_buffer_len(previous_size
);
1102 log_match_length(single_value
.n_elements
);
1104 TTCN_Logger::print_logmatch_buffer();
1106 TTCN_Logger::log_event_str(" with ");
1108 TTCN_Logger::log_event_str(" unmatched");
1112 const Record_Of_Type
* recof_value
= static_cast<const Record_Of_Type
*>(match_value
);
1113 if (template_selection
== SPECIFIC_VALUE
&&
1114 single_value
.n_elements
> 0 && get_number_of_permutations() == 0 &&
1115 single_value
.n_elements
== recof_value
->size_of()) {
1116 TTCN_Logger::log_event_str("{ ");
1117 for (int elem_count
= 0; elem_count
< single_value
.n_elements
; elem_count
++) {
1118 if (elem_count
> 0) TTCN_Logger::log_event_str(", ");
1119 single_value
.value_elements
[elem_count
]->log_matchv(recof_value
->get_at(elem_count
), legacy
);
1121 TTCN_Logger::log_event_str(" }");
1122 log_match_length(single_value
.n_elements
);
1125 TTCN_Logger::log_event_str(" with ");
1127 if (matchv(match_value
, legacy
)) TTCN_Logger::log_event_str(" matched");
1128 else TTCN_Logger::log_event_str(" unmatched");
1133 void Record_Of_Template::encode_text(Text_Buf
& text_buf
) const
1135 encode_text_permutation(text_buf
);
1136 switch (template_selection
) {
1137 case SPECIFIC_VALUE
:
1138 text_buf
.push_int(single_value
.n_elements
);
1139 for (int elem_count
= 0; elem_count
< single_value
.n_elements
; elem_count
++)
1140 single_value
.value_elements
[elem_count
]->encode_text(text_buf
);
1147 case COMPLEMENTED_LIST
:
1148 text_buf
.push_int(value_list
.n_values
);
1149 for (int list_count
= 0; list_count
< value_list
.n_values
; list_count
++)
1150 value_list
.list_value
[list_count
]->encode_text(text_buf
);
1153 TTCN_error("Text encoder: Encoding an uninitialized/unsupported template "
1154 "of type %s.", get_descriptor()->name
);
1158 void Record_Of_Template::decode_text(Text_Buf
& text_buf
)
1161 decode_text_permutation(text_buf
);
1162 switch (template_selection
) {
1163 case SPECIFIC_VALUE
:
1164 single_value
.n_elements
= text_buf
.pull_int().get_val();
1165 if (single_value
.n_elements
< 0)
1166 TTCN_error("Text decoder: Negative size was received for a template of "
1167 "type %s.", get_descriptor()->name
);
1168 single_value
.value_elements
= (Base_Template
**)allocate_pointers(single_value
.n_elements
);
1169 for (int elem_count
= 0; elem_count
< single_value
.n_elements
; elem_count
++) {
1170 single_value
.value_elements
[elem_count
] = create_elem();
1171 single_value
.value_elements
[elem_count
]->decode_text(text_buf
);
1179 case COMPLEMENTED_LIST
:
1180 value_list
.n_values
= text_buf
.pull_int().get_val();
1181 value_list
.list_value
= (Record_Of_Template
**)allocate_pointers(value_list
.n_values
);
1182 for (int list_count
= 0; list_count
< value_list
.n_values
; list_count
++) {
1183 value_list
.list_value
[list_count
] = create();
1184 value_list
.list_value
[list_count
]->decode_text(text_buf
);
1188 TTCN_error("Text decoder: An unknown/unsupported selection was received "
1189 "for a template of type %s.", get_descriptor()->name
);
1193 boolean
Record_Of_Template::is_present(boolean legacy
/* = FALSE */) const
1195 if (template_selection
==UNINITIALIZED_TEMPLATE
) return FALSE
;
1196 return !match_omit(legacy
);
1199 boolean
Record_Of_Template::match_omit(boolean legacy
/* = FALSE */) const
1201 if (is_ifpresent
) return TRUE
;
1202 switch (template_selection
) {
1207 case COMPLEMENTED_LIST
:
1209 // legacy behavior: 'omit' can appear in the value/complement list
1210 for (int i
=0; i
<value_list
.n_values
; i
++)
1211 if (value_list
.list_value
[i
]->match_omit())
1212 return template_selection
==VALUE_LIST
;
1213 return template_selection
==COMPLEMENTED_LIST
;
1215 // else fall through
1222 void Record_Of_Template::set_param(Module_Param
& param
)
1224 if (dynamic_cast<Module_Param_Name
*>(param
.get_id()) != NULL
&&
1225 param
.get_id()->next_name()) {
1226 // Haven't reached the end of the module parameter name
1227 // => the name refers to one of the elements, not to the whole record of
1228 char* param_field
= param
.get_id()->get_current_name();
1229 if (param_field
[0] < '0' || param_field
[0] > '9') {
1230 param
.error("Unexpected record field name in module parameter, expected a valid"
1231 " index for record of template type `%s'", get_descriptor()->name
);
1233 int param_index
= -1;
1234 sscanf(param_field
, "%d", ¶m_index
);
1235 get_at(param_index
)->set_param(param
);
1239 param
.basic_check(Module_Param::BC_TEMPLATE
|Module_Param::BC_LIST
, "record of template");
1241 Module_Param_Ptr mp
= ¶m
;
1242 if (param
.get_type() == Module_Param::MP_Reference
) {
1243 mp
= param
.get_referenced_param();
1246 switch (mp
->get_type()) {
1247 case Module_Param::MP_Omit
:
1248 set_value(OMIT_VALUE
);
1250 case Module_Param::MP_Any
:
1251 set_value(ANY_VALUE
);
1253 case Module_Param::MP_AnyOrNone
:
1254 set_value(ANY_OR_OMIT
);
1256 case Module_Param::MP_List_Template
:
1257 case Module_Param::MP_ComplementList_Template
: {
1258 Record_Of_Template
** list_items
= (Record_Of_Template
**)
1259 allocate_pointers(mp
->get_size());
1260 for (size_t i
= 0; i
< mp
->get_size(); i
++) {
1261 list_items
[i
] = create();
1262 list_items
[i
]->set_param(*mp
->get_elem(i
));
1265 template_selection
= mp
->get_type() == Module_Param::MP_List_Template
?
1266 VALUE_LIST
: COMPLEMENTED_LIST
;
1267 value_list
.n_values
= mp
->get_size();
1268 value_list
.list_value
= list_items
;
1270 case Module_Param::MP_Value_List
: {
1271 set_size(mp
->get_size()); // at least this size if there are no permutation elements, if there are then get_at() will automatically resize
1272 int curr_idx
= 0; // current index into this
1273 for (size_t i
=0; i
<mp
->get_size(); ++i
) {
1274 Module_Param
* const curr
= mp
->get_elem(i
);
1275 switch (curr
->get_type()) {
1276 case Module_Param::MP_NotUsed
:
1277 // skip this element
1280 case Module_Param::MP_Permutation_Template
: {
1281 // insert all elements from the permutation
1282 int perm_start_idx
= curr_idx
;
1283 for (size_t perm_i
=0; perm_i
<curr
->get_size(); perm_i
++) {
1284 get_at(curr_idx
)->set_param(*(curr
->get_elem(perm_i
)));
1287 int perm_end_idx
= curr_idx
- 1;
1288 add_permutation(perm_start_idx
, perm_end_idx
);
1291 get_at(curr_idx
)->set_param(*curr
);
1296 case Module_Param::MP_Indexed_List
:
1297 if (template_selection
!=SPECIFIC_VALUE
) set_size(0);
1298 for (size_t i
=0; i
<mp
->get_size(); ++i
) {
1299 Module_Param
* const current
= mp
->get_elem(i
);
1300 get_at((int)current
->get_id()->get_index())->set_param(*current
);
1304 param
.type_error("record of template", get_descriptor()->name
);
1306 is_ifpresent
= param
.get_ifpresent() || mp
->get_ifpresent();
1307 if (param
.get_length_restriction() != NULL
) {
1308 set_length_range(param
);
1311 set_length_range(*mp
);
1315 Module_Param
* Record_Of_Template::get_param(Module_Param_Name
& param_name
) const
1317 if (param_name
.next_name()) {
1318 // Haven't reached the end of the module parameter name
1319 // => the name refers to one of the elements, not to the whole record of
1320 char* param_field
= param_name
.get_current_name();
1321 if (param_field
[0] < '0' || param_field
[0] > '9') {
1322 TTCN_error("Unexpected record field name in module parameter reference, "
1323 "expected a valid index for record of template type `%s'",
1324 get_descriptor()->name
);
1326 int param_index
= -1;
1327 sscanf(param_field
, "%d", ¶m_index
);
1328 return get_at(param_index
)->get_param(param_name
);
1330 Module_Param
* mp
= NULL
;
1331 switch (template_selection
) {
1332 case UNINITIALIZED_TEMPLATE
:
1333 mp
= new Module_Param_Unbound();
1336 mp
= new Module_Param_Omit();
1339 mp
= new Module_Param_Any();
1342 mp
= new Module_Param_AnyOrNone();
1344 case SPECIFIC_VALUE
: {
1345 Vector
<Module_Param
*> values
;
1346 for (int i
= 0; i
< single_value
.n_elements
; ++i
) {
1347 values
.push_back(single_value
.value_elements
[i
]->get_param(param_name
));
1349 mp
= new Module_Param_Value_List();
1350 mp
->add_list_with_implicit_ids(&values
);
1354 case COMPLEMENTED_LIST
: {
1355 if (template_selection
== VALUE_LIST
) {
1356 mp
= new Module_Param_List_Template();
1359 mp
= new Module_Param_ComplementList_Template();
1361 for (int i
= 0; i
< value_list
.n_values
; ++i
) {
1362 mp
->add_elem(value_list
.list_value
[i
]->get_param(param_name
));
1369 mp
->set_ifpresent();
1371 mp
->set_length_restriction(get_length_range());
1375 void Record_Of_Template::check_restriction(template_res t_res
, const char* t_name
,
1376 boolean legacy
/* = FALSE */) const
1378 if (template_selection
==UNINITIALIZED_TEMPLATE
) return;
1379 switch ((t_name
&& (t_res
==TR_VALUE
)) ? TR_OMIT
: t_res
) {
1381 if (template_selection
==OMIT_VALUE
) return;
1384 if (template_selection
!=SPECIFIC_VALUE
|| is_ifpresent
) break;
1385 for (int i
=0; i
<single_value
.n_elements
; i
++)
1386 single_value
.value_elements
[i
]->check_restriction(t_res
, t_name
? t_name
: get_descriptor()->name
);
1389 if (!match_omit(legacy
)) return;
1394 TTCN_error("Restriction `%s' on template of type %s violated.",
1395 get_res_name(t_res
), t_name
? t_name
: get_descriptor()->name
);
1398 ////////////////////////////////////////////////////////////////////////////////
1400 void Set_Of_Template::substr_(int index
, int returncount
, Record_Of_Type
* rec_of
) const
1402 if (!is_value()) TTCN_error("The first argument of function substr() is a template of type %s with non-specific value.", get_descriptor()->name
);
1403 rec_of
->set_val(NULL_VALUE
);
1404 Base_Type
* this_value
= rec_of
->clone();
1405 valueofv(this_value
);
1406 static_cast<Record_Of_Type
*>(this_value
)->substr_(index
, returncount
, rec_of
);
1410 void Set_Of_Template::replace_(int index
, int len
,
1411 const Set_Of_Template
* repl
, Record_Of_Type
* rec_of
) const
1413 if (!is_value()) TTCN_error("The first argument of function replace() is a template of type %s with non-specific value.", get_descriptor()->name
);
1414 if (!repl
->is_value()) TTCN_error("The fourth argument of function replace() is a template of type %s with non-specific value.", repl
->get_descriptor()->name
);
1415 rec_of
->set_val(NULL_VALUE
);
1416 Base_Type
* this_value
= rec_of
->clone();
1417 valueofv(this_value
);
1418 Base_Type
* repl_value
= rec_of
->clone();
1419 repl
->valueofv(repl_value
);
1420 // call the replace() function of the value class instance
1421 static_cast<Record_Of_Type
*>(this_value
)->replace_(index
, len
, static_cast<Record_Of_Type
*>(repl_value
), rec_of
);
1426 void Set_Of_Template::replace_(int index
, int len
,
1427 const Record_Of_Type
* repl
, Record_Of_Type
* rec_of
) const
1429 if (!is_value()) TTCN_error("The first argument of function replace() is a template of type %s with non-specific value.", get_descriptor()->name
);
1430 rec_of
->set_val(NULL_VALUE
);
1431 Base_Type
* this_value
= rec_of
->clone();
1432 valueofv(this_value
);
1433 // call the replace() function of the value class instance
1434 static_cast<Record_Of_Type
*>(this_value
)->replace_(index
, len
, repl
, rec_of
);
1438 Set_Of_Template::Set_Of_Template(): err_descr(NULL
)
1442 Set_Of_Template::Set_Of_Template(template_sel other_value
)
1443 : Restricted_Length_Template(other_value
), err_descr(NULL
)
1447 Set_Of_Template::~Set_Of_Template()
1452 void Set_Of_Template::clean_up()
1454 switch (template_selection
) {
1455 case SPECIFIC_VALUE
:
1456 case SUPERSET_MATCH
:
1458 for (int elem_count
= 0; elem_count
< single_value
.n_elements
; elem_count
++)
1459 delete single_value
.value_elements
[elem_count
];
1460 free_pointers((void**)single_value
.value_elements
);
1463 case COMPLEMENTED_LIST
:
1464 for (int elem_count
= 0; elem_count
< value_list
.n_values
; elem_count
++)
1465 delete value_list
.list_value
[elem_count
];
1466 free_pointers((void**)value_list
.list_value
);
1471 template_selection
= UNINITIALIZED_TEMPLATE
;
1474 void Set_Of_Template::copy_value(const Base_Type
* other_value
)
1476 if (!other_value
->is_bound())
1477 TTCN_error("Initialization of a set of template with an unbound value.");
1478 const Record_Of_Type
* other_setof
= static_cast<const Record_Of_Type
*>(other_value
);
1479 single_value
.n_elements
= other_setof
->size_of();
1480 single_value
.value_elements
= (Base_Template
**)allocate_pointers(single_value
.n_elements
);
1481 for (int elem_count
= 0; elem_count
< single_value
.n_elements
; elem_count
++) {
1482 single_value
.value_elements
[elem_count
] = create_elem();
1483 single_value
.value_elements
[elem_count
]->copy_value(other_setof
->get_at(elem_count
));
1485 set_selection(SPECIFIC_VALUE
);
1486 err_descr
= other_setof
->get_err_descr();
1489 void Set_Of_Template::copy_optional(const Base_Type
* other_value
)
1491 if (other_value
->is_present()) {
1492 const Record_Of_Type
* other_setof
= static_cast<const Record_Of_Type
*>(other_value
->get_opt_value());
1493 copy_value(other_setof
);
1494 } else if (other_value
->is_bound()) {
1495 set_selection(OMIT_VALUE
);
1498 TTCN_error("Initialization of a set of template with an unbound optional field.");
1502 void Set_Of_Template::copy_template(const Set_Of_Template
& other_value
)
1504 switch (other_value
.template_selection
) {
1505 case SPECIFIC_VALUE
:
1506 case SUPERSET_MATCH
:
1508 single_value
.n_elements
= other_value
.single_value
.n_elements
;
1509 single_value
.value_elements
= (Base_Template
**)allocate_pointers(single_value
.n_elements
);
1510 for (int elem_count
= 0; elem_count
< single_value
.n_elements
; elem_count
++)
1511 single_value
.value_elements
[elem_count
] = other_value
.single_value
.value_elements
[elem_count
]->clone();
1518 case COMPLEMENTED_LIST
:
1519 value_list
.n_values
= other_value
.value_list
.n_values
;
1520 value_list
.list_value
= (Set_Of_Template
**)allocate_pointers(value_list
.n_values
);
1521 for (int list_count
= 0; list_count
< value_list
.n_values
; list_count
++)
1522 value_list
.list_value
[list_count
] = static_cast<Set_Of_Template
*>(other_value
.value_list
.list_value
[list_count
]->clone());
1525 TTCN_error("Copying an uninitialized/unsupported set of template");
1528 set_selection(other_value
);
1529 err_descr
= other_value
.err_descr
;
1532 Base_Template
* Set_Of_Template::clone() const
1534 Set_Of_Template
* setof
= create();
1535 setof
->copy_template(*this);
1539 Base_Template
* Set_Of_Template::get_at(int index_value
)
1541 if (index_value
< 0)
1542 TTCN_error("Accessing an element of a template for type %s using a "
1543 "negative index: %d.", get_descriptor()->name
, index_value
);
1544 if (template_selection
!= SPECIFIC_VALUE
||
1545 index_value
>= single_value
.n_elements
) set_size(index_value
+ 1);
1546 return single_value
.value_elements
[index_value
];
1549 Base_Template
* Set_Of_Template::get_at(const INTEGER
& index_value
)
1551 if (!index_value
.is_bound())
1552 TTCN_error("Using an unbound integer value for indexing a template of "
1553 "type %s.", get_descriptor()->name
);
1554 return get_at((int)index_value
);
1557 const Base_Template
* Set_Of_Template::get_at(int index_value
) const
1559 if (index_value
< 0)
1560 TTCN_error("Accessing an element of a template for type %s using "
1561 "a negative index: %d.", get_descriptor()->name
, index_value
);
1562 if (template_selection
!= SPECIFIC_VALUE
)
1563 TTCN_error("Accessing an element of a non-specific template for type %s.",
1564 get_descriptor()->name
);
1565 if (index_value
>= single_value
.n_elements
)
1566 TTCN_error("Index overflow in a template of type %s: The index is %d, but "
1567 "the template has only %d elements.", get_descriptor()->name
,
1568 index_value
, single_value
.n_elements
);
1569 return single_value
.value_elements
[index_value
];
1572 const Base_Template
* Set_Of_Template::get_at(const INTEGER
& index_value
) const
1574 if (!index_value
.is_bound())
1575 TTCN_error("Using an unbound integer value for indexing a template of "
1576 "type %s.", get_descriptor()->name
);
1577 return get_at((int)index_value
);
1580 void Set_Of_Template::set_size(int new_size
)
1583 TTCN_error("Internal error: Setting a negative size for a template of "
1584 "type %s.", get_descriptor()->name
);
1585 template_sel old_selection
= template_selection
;
1586 if (old_selection
!= SPECIFIC_VALUE
) {
1588 set_selection(SPECIFIC_VALUE
);
1589 single_value
.n_elements
= 0;
1590 single_value
.value_elements
= NULL
;
1592 if (new_size
> single_value
.n_elements
) {
1593 single_value
.value_elements
= (Base_Template
**)reallocate_pointers((void**)
1594 single_value
.value_elements
, single_value
.n_elements
, new_size
);
1595 if (old_selection
== ANY_VALUE
|| old_selection
== ANY_OR_OMIT
) {
1596 for (int elem_count
= single_value
.n_elements
;
1597 elem_count
< new_size
; elem_count
++) {
1598 single_value
.value_elements
[elem_count
] = create_elem();
1599 single_value
.value_elements
[elem_count
]->set_value(ANY_VALUE
);
1602 for (int elem_count
= single_value
.n_elements
;
1603 elem_count
< new_size
; elem_count
++)
1604 single_value
.value_elements
[elem_count
] = create_elem();
1606 single_value
.n_elements
= new_size
;
1607 } else if (new_size
< single_value
.n_elements
) {
1608 for (int elem_count
= new_size
;
1609 elem_count
< single_value
.n_elements
; elem_count
++)
1610 delete single_value
.value_elements
[elem_count
];
1611 single_value
.value_elements
= (Base_Template
**)reallocate_pointers((void**)
1612 single_value
.value_elements
, single_value
.n_elements
, new_size
);
1613 single_value
.n_elements
= new_size
;
1617 int Set_Of_Template::size_of(boolean is_size
) const
1619 const char* op_name
= is_size
? "size" : "length";
1621 boolean has_any_or_none
= FALSE
;
1623 TTCN_error("Performing %sof() operation on a template of type %s "
1624 "which has an ifpresent attribute.", op_name
, get_descriptor()->name
);
1625 switch (template_selection
)
1627 case SPECIFIC_VALUE
:
1628 case SUPERSET_MATCH
:
1629 case SUBSET_MATCH
: {
1631 has_any_or_none
= FALSE
;
1632 int elem_count
= single_value
.n_elements
;
1634 while (elem_count
>0 && !single_value
.value_elements
[elem_count
-1]->is_bound())
1637 for (int i
=0; i
<elem_count
; i
++)
1639 switch (single_value
.value_elements
[i
]->get_selection())
1642 TTCN_error("Performing %sof() operation on a template of type %s "
1643 "containing omit element.", op_name
, get_descriptor()->name
);
1645 has_any_or_none
= TRUE
;
1652 if (template_selection
==SUPERSET_MATCH
)
1654 has_any_or_none
= TRUE
;
1656 else if (template_selection
==SUBSET_MATCH
)
1658 int max_size
= min_size
;
1660 if (!has_any_or_none
) // [0,max_size]
1662 switch (length_restriction_type
)
1664 case NO_LENGTH_RESTRICTION
:
1665 if (max_size
==0) return 0;
1666 TTCN_error("Performing %sof() operation on a template of type "
1667 "%s with no exact size.", op_name
, get_descriptor()->name
);
1668 case SINGLE_LENGTH_RESTRICTION
:
1669 if (length_restriction
.single_length
<=max_size
)
1670 return length_restriction
.single_length
;
1671 TTCN_error("Performing %sof() operation on an invalid template of "
1672 "type %s. The maximum size (%d) contradicts the length restriction "
1673 "(%d).", op_name
, get_descriptor()->name
, max_size
,
1674 length_restriction
.single_length
);
1675 case RANGE_LENGTH_RESTRICTION
:
1676 if (max_size
==length_restriction
.range_length
.min_length
)
1678 else if (max_size
>length_restriction
.range_length
.min_length
)
1679 TTCN_error("Performing %sof() operation on a template of type %s "
1680 "with no exact size.", op_name
, get_descriptor()->name
);
1682 TTCN_error("Performing %sof() operation on an invalid template of "
1683 "type %s. Maximum size (%d) contradicts the length restriction "
1684 "(%d..%d).", op_name
, get_descriptor()->name
, max_size
,
1685 length_restriction
.range_length
.min_length
,
1686 length_restriction
.range_length
.max_length
);
1688 TTCN_error("Internal error: Template has invalid length restriction type.");
1694 TTCN_error("Performing %sof() operation on a template of type %s"
1695 " containing omit value.", op_name
, get_descriptor()->name
);
1699 has_any_or_none
= TRUE
;
1703 if (value_list
.n_values
<1)
1704 TTCN_error("Performing %sof() operation on a template of type %s "
1705 "containing an empty list.", op_name
, get_descriptor()->name
);
1706 int item_size
= value_list
.list_value
[0]->size_of(is_size
);
1707 for (int i
= 1; i
< value_list
.n_values
; i
++) {
1708 if (value_list
.list_value
[i
]->size_of(is_size
)!=item_size
)
1709 TTCN_error("Performing %sof() operation on a template of type %s "
1710 "containing a value list with different sizes.", op_name
, get_descriptor()->name
);
1712 min_size
= item_size
;
1713 has_any_or_none
= FALSE
;
1716 case COMPLEMENTED_LIST
:
1717 TTCN_error("Performing %sof() operation on a template of type %s "
1718 "containing complemented list.", op_name
, get_descriptor()->name
);
1719 case UNINITIALIZED_TEMPLATE
:
1721 case STRING_PATTERN
:
1722 TTCN_error("Performing %sof() operation on an uninitialized/unsupported "
1723 "template of type %s.", op_name
, get_descriptor()->name
);
1725 return check_section_is_single(min_size
, has_any_or_none
, op_name
,
1726 "a template of type", get_descriptor()->name
);
1729 int Set_Of_Template::n_elem() const
1731 switch (template_selection
) {
1732 case SPECIFIC_VALUE
:
1733 case SUPERSET_MATCH
:
1735 return single_value
.n_elements
;
1737 case COMPLEMENTED_LIST
:
1738 TTCN_error("Performing n_elem() operation on a template of type %s "
1739 "containing complemented list.", get_descriptor()->name
);
1741 case UNINITIALIZED_TEMPLATE
:
1747 case STRING_PATTERN
:
1750 TTCN_error("Performing n_elem() operation on an uninitialized/unsupported "
1751 "template of type %s.", get_descriptor()->name
);
1754 boolean
Set_Of_Template::match_function_specific(
1755 const Base_Type
*value_ptr
, int value_index
,
1756 const Restricted_Length_Template
*template_ptr
, int template_index
,
1759 const Set_Of_Template
* set_tmpl_ptr
= static_cast<const Set_Of_Template
*>(template_ptr
);
1760 if (value_index
>= 0) {
1761 const Record_Of_Type
* recof_ptr
= static_cast<const Record_Of_Type
*>(value_ptr
);
1762 return set_tmpl_ptr
->single_value
.value_elements
[template_index
]->matchv(recof_ptr
->get_at(value_index
), legacy
);
1764 return set_tmpl_ptr
->single_value
.value_elements
[template_index
]->is_any_or_omit();
1768 boolean
Set_Of_Template::match_function_set(
1769 const Base_Type
*value_ptr
, int value_index
,
1770 const Restricted_Length_Template
*template_ptr
, int template_index
,
1773 const Set_Of_Template
* set_tmpl_ptr
= static_cast<const Set_Of_Template
*>(template_ptr
);
1774 if (value_index
>= 0) {
1775 const Record_Of_Type
* recof_ptr
= static_cast<const Record_Of_Type
*>(value_ptr
);
1776 return set_tmpl_ptr
->single_value
.value_elements
[template_index
]->matchv(recof_ptr
->get_at(value_index
), legacy
);
1778 return set_tmpl_ptr
->single_value
.value_elements
[template_index
]->is_any_or_omit();
1782 void Set_Of_Template::log_function(
1783 const Base_Type
*value_ptr
, const Restricted_Length_Template
*template_ptr
,
1784 int index_value
, int index_template
, boolean legacy
)
1786 const Set_Of_Template
* set_tmpl_ptr
= static_cast<const Set_Of_Template
*>(template_ptr
);
1787 const Record_Of_Type
* recof_ptr
= static_cast<const Record_Of_Type
*>(value_ptr
);
1788 if (value_ptr
!= NULL
&& template_ptr
!= NULL
)
1789 set_tmpl_ptr
->single_value
.value_elements
[index_template
]->log_matchv(recof_ptr
->get_at(index_value
), legacy
);
1790 else if (value_ptr
!= NULL
)
1791 recof_ptr
->get_at(index_value
)->log();
1792 else if (template_ptr
!= NULL
)
1793 set_tmpl_ptr
->single_value
.value_elements
[index_template
]->log();
1796 boolean
Set_Of_Template::matchv(const Base_Type
* other_value
,
1797 boolean legacy
) const
1799 const Record_Of_Type
* other_recof
= static_cast<const Record_Of_Type
*>(other_value
);
1800 if (!other_recof
->is_bound())
1801 TTCN_error("Matching an unbound value of type %s with a template.",
1802 other_recof
->get_descriptor()->name
);
1803 int value_length
= other_recof
->size_of();
1804 if (!match_length(value_length
)) return FALSE
;
1805 switch (template_selection
) {
1806 case SPECIFIC_VALUE
:
1807 return match_set_of(other_recof
, value_length
, this,
1808 single_value
.n_elements
, match_function_specific
, legacy
);
1815 case COMPLEMENTED_LIST
:
1816 for (int list_count
= 0; list_count
< value_list
.n_values
; list_count
++)
1817 if (value_list
.list_value
[list_count
]->matchv(other_recof
, legacy
))
1818 return template_selection
== VALUE_LIST
;
1819 return template_selection
== COMPLEMENTED_LIST
;
1820 case SUPERSET_MATCH
:
1822 return match_set_of(other_recof
, value_length
, this,
1823 single_value
.n_elements
, match_function_set
, legacy
);
1825 TTCN_error("Matching with an uninitialized/unsupported template of type %s.",
1826 get_descriptor()->name
);
1831 boolean
Set_Of_Template::is_value() const
1833 if (template_selection
!= SPECIFIC_VALUE
|| is_ifpresent
) return FALSE
;
1834 for (int elem_count
= 0; elem_count
< single_value
.n_elements
; elem_count
++)
1835 if (!single_value
.value_elements
[elem_count
]->is_value()) return FALSE
;
1839 void Set_Of_Template::valueofv(Base_Type
* value
) const
1841 if (template_selection
!= SPECIFIC_VALUE
|| is_ifpresent
)
1842 TTCN_error("Performing a valueof or send operation on a non-specific template of type %s.", get_descriptor()->name
);
1843 Record_Of_Type
* setof_value
= static_cast<Record_Of_Type
*>(value
);
1844 setof_value
->set_size(single_value
.n_elements
);
1845 for (int elem_count
= 0; elem_count
< single_value
.n_elements
; elem_count
++)
1846 single_value
.value_elements
[elem_count
]->valueofv(setof_value
->get_at(elem_count
));
1847 setof_value
->set_err_descr(err_descr
);
1850 void Set_Of_Template::set_value(template_sel other_value
)
1852 check_single_selection(other_value
);
1854 set_selection(other_value
);
1858 void Set_Of_Template::set_type(template_sel template_type
, int list_length
)
1861 switch (template_type
) {
1863 case COMPLEMENTED_LIST
:
1864 value_list
.n_values
= list_length
;
1865 value_list
.list_value
= (Set_Of_Template
**)allocate_pointers(value_list
.n_values
);
1866 for (int list_count
= 0; list_count
< value_list
.n_values
; list_count
++)
1867 value_list
.list_value
[list_count
] = create();
1869 case SUPERSET_MATCH
:
1871 single_value
.n_elements
= list_length
;
1872 single_value
.value_elements
= (Base_Template
**)allocate_pointers(single_value
.n_elements
);
1873 for (int set_count
= 0; set_count
< single_value
.n_elements
; set_count
++)
1874 single_value
.value_elements
[set_count
] = create_elem();
1877 TTCN_error("Internal error: Setting an invalid type for a template of "
1878 "type %s.", get_descriptor()->name
);
1880 set_selection(template_type
);
1883 Set_Of_Template
* Set_Of_Template::get_list_item(int list_index
)
1885 if (template_selection
!= VALUE_LIST
&& template_selection
!= COMPLEMENTED_LIST
)
1886 TTCN_error("Internal error: Accessing a list element of a non-list "
1887 "template of type %s.", get_descriptor()->name
);
1888 if (list_index
>= value_list
.n_values
|| list_index
< 0)
1889 TTCN_error("Internal error: Index overflow in a value list template "
1890 "of type %s.", get_descriptor()->name
);
1891 return value_list
.list_value
[list_index
];
1894 Base_Template
* Set_Of_Template::get_set_item(int set_index
)
1896 if (template_selection
!= SUPERSET_MATCH
&& template_selection
!= SUBSET_MATCH
)
1897 TTCN_error("Internal error: Accessing a set element of a non-set "
1898 "template of type %s.", get_descriptor()->name
);
1899 if (set_index
>= single_value
.n_elements
|| set_index
< 0)
1900 TTCN_error("Internal error: Index overflow in a set template of "
1901 "type %s.", get_descriptor()->name
);
1902 return single_value
.value_elements
[set_index
];
1905 void Set_Of_Template::log() const
1907 switch (template_selection
) {
1908 case SPECIFIC_VALUE
:
1909 if (single_value
.n_elements
> 0) {
1910 TTCN_Logger::log_event_str("{ ");
1911 for (int elem_count
= 0; elem_count
< single_value
.n_elements
; elem_count
++) {
1912 if (elem_count
> 0) TTCN_Logger::log_event_str(", ");
1913 single_value
.value_elements
[elem_count
]->log();
1915 TTCN_Logger::log_event_str(" }");
1916 } else TTCN_Logger::log_event_str("{ }");
1918 case COMPLEMENTED_LIST
:
1919 TTCN_Logger::log_event_str("complement ");
1922 TTCN_Logger::log_char('(');
1923 for (int list_count
= 0; list_count
< value_list
.n_values
; list_count
++) {
1924 if (list_count
> 0) TTCN_Logger::log_event_str(", ");
1925 value_list
.list_value
[list_count
]->log();
1927 TTCN_Logger::log_char(')');
1929 case SUPERSET_MATCH
:
1931 TTCN_Logger::log_event("%s(",
1932 template_selection
== SUPERSET_MATCH
? "superset" : "subset");
1933 for (int set_count
= 0; set_count
< single_value
.n_elements
; set_count
++) {
1934 if (set_count
> 0) TTCN_Logger::log_event_str(", ");
1935 single_value
.value_elements
[set_count
]->log();
1937 TTCN_Logger::log_char(')');
1945 if (err_descr
) err_descr
->log();
1948 void Set_Of_Template::log_matchv(const Base_Type
* match_value
, boolean legacy
) const
1950 if (TTCN_Logger::VERBOSITY_COMPACT
== TTCN_Logger::get_matching_verbosity()) {
1951 if (matchv(match_value
, legacy
)) {
1952 TTCN_Logger::print_logmatch_buffer();
1953 TTCN_Logger::log_event_str(" matched");
1955 size_t previous_size
= TTCN_Logger::get_logmatch_buffer_len();
1956 if (template_selection
== SPECIFIC_VALUE
) {
1957 const Record_Of_Type
* setof_value
= static_cast<const Record_Of_Type
*>(match_value
);
1958 log_match_heuristics(setof_value
, setof_value
->size_of(), this,
1959 single_value
.n_elements
, match_function_specific
, log_function
, legacy
);
1961 if (previous_size
!= 0) {
1962 TTCN_Logger::print_logmatch_buffer();
1963 TTCN_Logger::set_logmatch_buffer_len(previous_size
);
1964 TTCN_Logger::log_event_str(":=");
1967 TTCN_Logger::log_event_str(" with ");
1969 TTCN_Logger::log_event_str(" unmatched");
1974 TTCN_Logger::log_event_str(" with ");
1976 if (matchv(match_value
, legacy
)) TTCN_Logger::log_event_str(" matched");
1978 TTCN_Logger::log_event_str(" unmatched");
1979 if (template_selection
== SPECIFIC_VALUE
) {
1980 const Record_Of_Type
* setof_value
= static_cast<const Record_Of_Type
*>(match_value
);
1981 log_match_heuristics(setof_value
, setof_value
->size_of(), this,
1982 single_value
.n_elements
, match_function_specific
, log_function
, legacy
);
1988 void Set_Of_Template::encode_text(Text_Buf
& text_buf
) const
1990 encode_text_restricted(text_buf
);
1991 switch (template_selection
) {
1992 case SPECIFIC_VALUE
:
1993 case SUPERSET_MATCH
:
1995 text_buf
.push_int(single_value
.n_elements
);
1996 for (int elem_count
= 0; elem_count
< single_value
.n_elements
; elem_count
++)
1997 single_value
.value_elements
[elem_count
]->encode_text(text_buf
);
2004 case COMPLEMENTED_LIST
:
2005 text_buf
.push_int(value_list
.n_values
);
2006 for (int list_count
= 0; list_count
< value_list
.n_values
; list_count
++)
2007 value_list
.list_value
[list_count
]->encode_text(text_buf
);
2010 TTCN_error("Text encoder: Encoding an uninitialized/unsupported template "
2011 "of type %s.", get_descriptor()->name
);
2015 void Set_Of_Template::decode_text(Text_Buf
& text_buf
)
2018 decode_text_restricted(text_buf
);
2019 switch (template_selection
) {
2020 case SPECIFIC_VALUE
:
2021 case SUPERSET_MATCH
:
2023 single_value
.n_elements
= text_buf
.pull_int().get_val();
2024 if (single_value
.n_elements
< 0)
2025 TTCN_error("Text decoder: Negative size was received for a template of "
2026 "type %s.", get_descriptor()->name
);
2027 single_value
.value_elements
= (Base_Template
**)allocate_pointers(single_value
.n_elements
);
2028 for (int elem_count
= 0; elem_count
< single_value
.n_elements
; elem_count
++) {
2029 single_value
.value_elements
[elem_count
] = create_elem();
2030 single_value
.value_elements
[elem_count
]->decode_text(text_buf
);
2038 case COMPLEMENTED_LIST
:
2039 value_list
.n_values
= text_buf
.pull_int().get_val();
2040 value_list
.list_value
= (Set_Of_Template
**)allocate_pointers(value_list
.n_values
);
2041 for (int list_count
= 0; list_count
< value_list
.n_values
; list_count
++) {
2042 value_list
.list_value
[list_count
] = create();
2043 value_list
.list_value
[list_count
]->decode_text(text_buf
);
2047 TTCN_error("Text decoder: An unknown/unsupported selection was received "
2048 "for a template of type %s.", get_descriptor()->name
);
2052 boolean
Set_Of_Template::is_present(boolean legacy
/* = FALSE */) const
2054 if (template_selection
==UNINITIALIZED_TEMPLATE
) return FALSE
;
2055 return !match_omit(legacy
);
2058 boolean
Set_Of_Template::match_omit(boolean legacy
/* = FALSE */) const
2060 if (is_ifpresent
) return TRUE
;
2061 switch (template_selection
) {
2066 case COMPLEMENTED_LIST
:
2068 // legacy behavior: 'omit' can appear in the value/complement list
2069 for (int i
=0; i
<value_list
.n_values
; i
++)
2070 if (value_list
.list_value
[i
]->match_omit())
2071 return template_selection
==VALUE_LIST
;
2072 return template_selection
==COMPLEMENTED_LIST
;
2074 // else fall through
2081 void Set_Of_Template::set_param(Module_Param
& param
)
2083 if (dynamic_cast<Module_Param_Name
*>(param
.get_id()) != NULL
&&
2084 param
.get_id()->next_name()) {
2085 // Haven't reached the end of the module parameter name
2086 // => the name refers to one of the elements, not to the whole record of
2087 char* param_field
= param
.get_id()->get_current_name();
2088 if (param_field
[0] < '0' || param_field
[0] > '9') {
2089 param
.error("Unexpected record field name in module parameter, expected a valid"
2090 " index for set of template type `%s'", get_descriptor()->name
);
2092 int param_index
= -1;
2093 sscanf(param_field
, "%d", ¶m_index
);
2094 get_at(param_index
)->set_param(param
);
2098 param
.basic_check(Module_Param::BC_TEMPLATE
|Module_Param::BC_LIST
, "set of template");
2100 Module_Param_Ptr mp
= ¶m
;
2101 if (param
.get_type() == Module_Param::MP_Reference
) {
2102 mp
= param
.get_referenced_param();
2105 switch (mp
->get_type()) {
2106 case Module_Param::MP_Omit
:
2107 set_value(OMIT_VALUE
);
2109 case Module_Param::MP_Any
:
2110 set_value(ANY_VALUE
);
2112 case Module_Param::MP_AnyOrNone
:
2113 set_value(ANY_OR_OMIT
);
2115 case Module_Param::MP_List_Template
:
2116 case Module_Param::MP_ComplementList_Template
: {
2117 Set_Of_Template
** list_items
= (Set_Of_Template
**)
2118 allocate_pointers(mp
->get_size());
2119 for (size_t i
= 0; i
< mp
->get_size(); i
++) {
2120 list_items
[i
] = create();
2121 list_items
[i
]->set_param(*mp
->get_elem(i
));
2124 template_selection
= mp
->get_type() == Module_Param::MP_List_Template
?
2125 VALUE_LIST
: COMPLEMENTED_LIST
;
2126 value_list
.n_values
= mp
->get_size();
2127 value_list
.list_value
= list_items
;
2129 case Module_Param::MP_Value_List
:
2130 set_size(mp
->get_size());
2131 for (size_t i
=0; i
<mp
->get_size(); ++i
) {
2132 Module_Param
* const curr
= mp
->get_elem(i
);
2133 if (curr
->get_type()!=Module_Param::MP_NotUsed
) {
2134 get_at(i
)->set_param(*curr
);
2138 case Module_Param::MP_Indexed_List
:
2139 if (template_selection
!=SPECIFIC_VALUE
) set_size(0);
2140 for (size_t i
=0; i
<mp
->get_size(); ++i
) {
2141 Module_Param
* const current
= mp
->get_elem(i
);
2142 get_at((int)current
->get_id()->get_index())->set_param(*current
);
2145 case Module_Param::MP_Superset_Template
:
2146 case Module_Param::MP_Subset_Template
:
2147 set_type(mp
->get_type()==Module_Param::MP_Superset_Template
? SUPERSET_MATCH
: SUBSET_MATCH
, mp
->get_size());
2148 for (size_t i
=0; i
<mp
->get_size(); i
++) {
2149 get_set_item((int)i
)->set_param(*mp
->get_elem(i
));
2153 param
.type_error("set of template", get_descriptor()->name
);
2155 is_ifpresent
= param
.get_ifpresent() || mp
->get_ifpresent();
2156 if (param
.get_length_restriction() != NULL
) {
2157 set_length_range(param
);
2160 set_length_range(*mp
);
2164 Module_Param
* Set_Of_Template::get_param(Module_Param_Name
& param_name
) const
2166 if (param_name
.next_name()) {
2167 // Haven't reached the end of the module parameter name
2168 // => the name refers to one of the elements, not to the whole record of
2169 char* param_field
= param_name
.get_current_name();
2170 if (param_field
[0] < '0' || param_field
[0] > '9') {
2171 TTCN_error("Unexpected record field name in module parameter reference, "
2172 "expected a valid index for set of template type `%s'",
2173 get_descriptor()->name
);
2175 int param_index
= -1;
2176 sscanf(param_field
, "%d", ¶m_index
);
2177 return get_at(param_index
)->get_param(param_name
);
2179 Module_Param
* mp
= NULL
;
2180 switch (template_selection
) {
2181 case UNINITIALIZED_TEMPLATE
:
2182 mp
= new Module_Param_Unbound();
2185 mp
= new Module_Param_Omit();
2188 mp
= new Module_Param_Any();
2191 mp
= new Module_Param_AnyOrNone();
2193 case SPECIFIC_VALUE
: {
2194 Vector
<Module_Param
*> values
;
2195 for (int i
= 0; i
< single_value
.n_elements
; ++i
) {
2196 values
.push_back(single_value
.value_elements
[i
]->get_param(param_name
));
2198 mp
= new Module_Param_Value_List();
2199 mp
->add_list_with_implicit_ids(&values
);
2203 case COMPLEMENTED_LIST
: {
2204 if (template_selection
== VALUE_LIST
) {
2205 mp
= new Module_Param_List_Template();
2208 mp
= new Module_Param_ComplementList_Template();
2210 for (int i
= 0; i
< value_list
.n_values
; ++i
) {
2211 mp
->add_elem(value_list
.list_value
[i
]->get_param(param_name
));
2218 mp
->set_ifpresent();
2220 mp
->set_length_restriction(get_length_range());
2224 void Set_Of_Template::check_restriction(template_res t_res
, const char* t_name
,
2225 boolean legacy
/* = FALSE */) const
2227 if (template_selection
==UNINITIALIZED_TEMPLATE
) return;
2228 switch ((t_name
&&(t_res
==TR_VALUE
))?TR_OMIT
:t_res
) {
2230 if (template_selection
==OMIT_VALUE
) return;
2233 if (template_selection
!=SPECIFIC_VALUE
|| is_ifpresent
) break;
2234 for (int i
=0; i
<single_value
.n_elements
; i
++)
2235 single_value
.value_elements
[i
]->check_restriction(t_res
, t_name
? t_name
: get_descriptor()->name
);
2238 if (!match_omit(legacy
)) return;
2243 TTCN_error("Restriction `%s' on template of type %s violated.",
2244 get_res_name(t_res
), t_name
? t_name
: get_descriptor()->name
);
2247 ////////////////////////////////////////////////////////////////////////////////
2249 Record_Template::Record_Template(): Base_Template(), err_descr(NULL
)
2253 Record_Template::Record_Template(template_sel other_value
):
2254 Base_Template(other_value
), err_descr(NULL
)
2256 check_single_selection(other_value
);
2259 Record_Template::~Record_Template()
2264 void Record_Template::clean_up()
2266 switch (template_selection
) {
2267 case SPECIFIC_VALUE
:
2268 for (int elem_count
= 0; elem_count
< single_value
.n_elements
; elem_count
++)
2269 delete single_value
.value_elements
[elem_count
];
2270 free_pointers((void**)single_value
.value_elements
);
2273 case COMPLEMENTED_LIST
:
2274 for (int elem_count
= 0; elem_count
< value_list
.n_values
; elem_count
++)
2275 delete value_list
.list_value
[elem_count
];
2276 free_pointers((void**)value_list
.list_value
);
2281 template_selection
= UNINITIALIZED_TEMPLATE
;
2284 void Record_Template::copy_value(const Base_Type
* other_value
)
2286 if (!other_value
->is_bound())
2287 TTCN_error("Initialization of a record/set template with an unbound value.");
2289 const Record_Type
* other_rec
= static_cast<const Record_Type
*>(other_value
);
2290 const int* optional_indexes
= other_rec
->get_optional_indexes();
2291 int next_optional_idx
= 0;
2292 for (int elem_count
= 0; elem_count
< single_value
.n_elements
; elem_count
++) {
2293 boolean is_optional
= optional_indexes
&& (optional_indexes
[next_optional_idx
]==elem_count
);
2294 if (is_optional
) next_optional_idx
++;
2295 const Base_Type
* elem_value
= other_rec
->get_at(elem_count
);
2296 if (!elem_value
->is_bound()) continue;
2298 if (elem_value
->is_present()) {
2299 single_value
.value_elements
[elem_count
]->copy_value(other_rec
->get_at(elem_count
)->get_opt_value());
2301 single_value
.value_elements
[elem_count
]->set_value(OMIT_VALUE
);
2304 single_value
.value_elements
[elem_count
]->copy_value(other_rec
->get_at(elem_count
));
2307 err_descr
= other_rec
->get_err_descr();
2310 void Record_Template::copy_template(const Record_Template
& other_value
)
2312 switch (other_value
.template_selection
) {
2313 case SPECIFIC_VALUE
:
2314 set_specific(); // FIXME: create_elem(int elem_idx) should be used, but that's more code to generate...
2315 // single_value.n_elements = other_value.single_value.n_elements;
2316 // single_value.value_elements = (Base_Template**)allocate_pointers(single_value.n_elements);
2317 for (int elem_count
= 0; elem_count
< single_value
.n_elements
; elem_count
++) {
2318 if (other_value
.single_value
.value_elements
[elem_count
]->is_bound()) {
2319 delete single_value
.value_elements
[elem_count
]; // FIXME: unbound elements should not be created when the element is bound
2320 single_value
.value_elements
[elem_count
] = other_value
.single_value
.value_elements
[elem_count
]->clone();
2329 case COMPLEMENTED_LIST
:
2330 value_list
.n_values
= other_value
.value_list
.n_values
;
2331 value_list
.list_value
= (Record_Template
**)allocate_pointers(value_list
.n_values
);
2332 for (int list_count
= 0; list_count
< value_list
.n_values
; list_count
++) {
2333 if (other_value
.value_list
.list_value
[list_count
]->is_bound()) {
2334 value_list
.list_value
[list_count
] = static_cast<Record_Template
*>(other_value
.value_list
.list_value
[list_count
]->clone());
2336 value_list
.list_value
[list_count
] = create();
2341 TTCN_error("Copying an uninitialized/unsupported record/set template.");
2344 set_selection(other_value
);
2345 err_descr
= other_value
.err_descr
;
2348 void Record_Template::copy_optional(const Base_Type
* other_value
)
2350 if (other_value
->is_present()) {
2351 const Record_Type
* other_rec
= static_cast<const Record_Type
*>(other_value
->get_opt_value());
2352 copy_value(other_rec
);
2353 } else if (other_value
->is_bound()) {
2354 set_selection(OMIT_VALUE
);
2357 TTCN_error("Initialization of a record/set template with an unbound optional field.");
2361 void Record_Template::set_type(template_sel template_type
, int list_length
)
2363 if (template_type
!= VALUE_LIST
&& template_type
!= COMPLEMENTED_LIST
)
2364 TTCN_error("Setting an invalid list for a template of type %s.", get_descriptor()->name
);
2366 set_selection(template_type
);
2367 value_list
.n_values
= list_length
;
2368 value_list
.list_value
= (Record_Template
**)allocate_pointers(value_list
.n_values
);
2369 for (int list_count
= 0; list_count
< value_list
.n_values
; list_count
++)
2370 value_list
.list_value
[list_count
] = create();
2373 Record_Template
* Record_Template::get_list_item(int list_index
) const
2375 if (template_selection
!= VALUE_LIST
&& template_selection
!= COMPLEMENTED_LIST
)
2376 TTCN_error("Accessing a list element of a non-list template of type %s.", get_descriptor()->name
);
2377 if (list_index
>= value_list
.n_values
|| list_index
< 0)
2378 TTCN_error("Index overflow in a value list template of type %s.", get_descriptor()->name
);
2379 return value_list
.list_value
[list_index
];
2382 int Record_Template::size_of() const
2385 TTCN_error("Performing sizeof() operation on a template of type %s "
2386 "which has an ifpresent attribute.", get_descriptor()->name
);
2387 switch (template_selection
)
2389 case SPECIFIC_VALUE
: {
2391 for (int elem_count
= 0; elem_count
< single_value
.n_elements
; elem_count
++)
2392 if (single_value
.value_elements
[elem_count
]->is_present()) my_size
++;
2396 if (value_list
.n_values
<1)
2397 TTCN_error("Internal error: Performing sizeof() operation on a template of type %s containing an empty list.", get_descriptor()->name
);
2398 int item_size
= value_list
.list_value
[0]->size_of();
2399 for (int i
= 1; i
< value_list
.n_values
; i
++)
2400 if (value_list
.list_value
[i
]->size_of()!=item_size
)
2401 TTCN_error("Performing sizeof() operation on a template of type %s containing a value list with different sizes.", get_descriptor()->name
);
2405 TTCN_error("Performing sizeof() operation on a template of type %s containing omit value.", get_descriptor()->name
);
2408 TTCN_error("Performing sizeof() operation on a template of type %s containing */? value.", get_descriptor()->name
);
2409 case COMPLEMENTED_LIST
:
2410 TTCN_error("Performing sizeof() operation on a template of type %s containing complemented list.", get_descriptor()->name
);
2412 TTCN_error("Performing sizeof() operation on an uninitialized/unsupported template of type %s.", get_descriptor()->name
);
2417 boolean
Record_Template::is_value() const
2419 if (template_selection
!= SPECIFIC_VALUE
|| is_ifpresent
) return FALSE
;
2420 for (int elem_count
= 0; elem_count
< single_value
.n_elements
; elem_count
++) {
2421 const Base_Template
* tmpl_elem
= single_value
.value_elements
[elem_count
];
2422 if (tmpl_elem
->get_selection()!=OMIT_VALUE
&& !tmpl_elem
->is_value()) return FALSE
;
2427 void Record_Template::valueofv(Base_Type
* value
) const
2429 if (template_selection
!= SPECIFIC_VALUE
|| is_ifpresent
)
2430 TTCN_error("Performing a valueof or send operation on a non-specific template of type %s.", get_descriptor()->name
);
2431 Record_Type
* rec_value
= static_cast<Record_Type
*>(value
);
2432 const int* optional_indexes
= rec_value
->get_optional_indexes();
2433 int next_optional_idx
= 0;
2434 for (int elem_count
= 0; elem_count
< single_value
.n_elements
; elem_count
++) {
2435 boolean is_optional
= optional_indexes
&& (optional_indexes
[next_optional_idx
]==elem_count
);
2437 if (single_value
.value_elements
[elem_count
]->get_selection()==OMIT_VALUE
) {
2438 rec_value
->get_at(elem_count
)->set_to_omit();
2440 rec_value
->get_at(elem_count
)->set_to_present(); // create instance of optional value object
2441 single_value
.value_elements
[elem_count
]->valueofv(rec_value
->get_at(elem_count
)->get_opt_value());
2444 single_value
.value_elements
[elem_count
]->valueofv(rec_value
->get_at(elem_count
));
2446 if (is_optional
) next_optional_idx
++;
2448 rec_value
->set_err_descr(err_descr
);
2451 void Record_Template::set_value(template_sel other_value
)
2453 check_single_selection(other_value
);
2455 set_selection(other_value
);
2459 Base_Template
* Record_Template::get_at(int index_value
)
2462 if (index_value
< 0 || index_value
>= single_value
.n_elements
)
2463 TTCN_error("Internal error: accessing an element of a template of type %s using an "
2464 "invalid index: %d.", get_descriptor()->name
, index_value
);
2465 return single_value
.value_elements
[index_value
];
2468 const Base_Template
* Record_Template::get_at(int index_value
) const
2470 if (index_value
< 0 || index_value
>= single_value
.n_elements
)
2471 TTCN_error("Internal error: accessing an element of a template of type %s using an "
2472 "invalid index: %d.", get_descriptor()->name
, index_value
);
2473 if (template_selection
!= SPECIFIC_VALUE
)
2474 TTCN_error("Accessing field %s of a non-specific template of type %s.",
2475 fld_name(index_value
), get_descriptor()->name
);
2476 return single_value
.value_elements
[index_value
];
2479 Base_Template
* Record_Template::clone() const
2481 Record_Template
* rec
= create();
2482 rec
->copy_template(*this);
2486 void Record_Template::log() const
2488 switch (template_selection
) {
2489 case SPECIFIC_VALUE
:
2490 if (single_value
.n_elements
> 0) {
2491 TTCN_Logger::log_event_str("{ ");
2492 for (int elem_count
= 0; elem_count
< single_value
.n_elements
; elem_count
++) {
2493 if (elem_count
> 0) TTCN_Logger::log_event_str(", ");
2494 TTCN_Logger::log_event_str(fld_name(elem_count
));
2495 TTCN_Logger::log_event_str(" := ");
2496 single_value
.value_elements
[elem_count
]->log();
2498 TTCN_Logger::log_event_str(" }");
2499 } else TTCN_Logger::log_event_str("{ }");
2501 case COMPLEMENTED_LIST
:
2502 TTCN_Logger::log_event_str("complement ");
2505 TTCN_Logger::log_char('(');
2506 for (int list_count
= 0; list_count
< value_list
.n_values
; list_count
++) {
2507 if (list_count
> 0) TTCN_Logger::log_event_str(", ");
2508 value_list
.list_value
[list_count
]->log();
2510 TTCN_Logger::log_char(')');
2517 if (err_descr
) err_descr
->log();
2520 boolean
Record_Template::matchv(const Base_Type
* other_value
,
2521 boolean legacy
) const
2523 switch (template_selection
) {
2529 case SPECIFIC_VALUE
: {
2530 const Record_Type
* other_rec
= static_cast<const Record_Type
*>(other_value
);
2531 const int* optional_indexes
= other_rec
->get_optional_indexes();
2532 int next_optional_idx
= 0;
2533 for (int elem_count
= 0; elem_count
< single_value
.n_elements
; elem_count
++) {
2534 boolean is_optional
= optional_indexes
&& (optional_indexes
[next_optional_idx
]==elem_count
);
2535 const Base_Template
* elem_tmpl
= single_value
.value_elements
[elem_count
];
2536 const Base_Type
* elem_value
= other_rec
->get_at(elem_count
);
2537 if (!elem_value
->is_bound()) return FALSE
;
2538 boolean elem_match
= is_optional
?
2539 ( elem_value
->ispresent() ? elem_tmpl
->matchv(elem_value
->get_opt_value(), legacy
) : elem_tmpl
->match_omit(legacy
) ) :
2540 elem_tmpl
->matchv(other_rec
->get_at(elem_count
), legacy
);
2541 if (!elem_match
) return FALSE
;
2542 if (is_optional
) next_optional_idx
++;
2546 case COMPLEMENTED_LIST
:
2547 for (int list_count
= 0; list_count
< value_list
.n_values
; list_count
++)
2548 if (value_list
.list_value
[list_count
]->matchv(other_value
, legacy
)) return template_selection
== VALUE_LIST
;
2549 return template_selection
== COMPLEMENTED_LIST
;
2551 TTCN_error("Matching an uninitialized/unsupported template of type %s.", get_descriptor()->name
);
2556 void Record_Template::log_matchv(const Base_Type
* match_value
, boolean legacy
) const
2558 if (TTCN_Logger::VERBOSITY_COMPACT
== TTCN_Logger::get_matching_verbosity()) {
2559 if (matchv(match_value
, legacy
)) {
2560 TTCN_Logger::print_logmatch_buffer();
2561 TTCN_Logger::log_event_str(" matched");
2563 if (template_selection
== SPECIFIC_VALUE
) {
2564 size_t previous_size
= TTCN_Logger::get_logmatch_buffer_len();
2565 const Record_Type
* match_rec
= static_cast<const Record_Type
*>(match_value
);
2566 const int* optional_indexes
= match_rec
->get_optional_indexes();
2567 int next_optional_idx
= 0;
2568 for (int elem_count
= 0; elem_count
< single_value
.n_elements
; elem_count
++) {
2569 boolean is_optional
= optional_indexes
&& (optional_indexes
[next_optional_idx
]==elem_count
);
2570 const Base_Template
* elem_tmpl
= single_value
.value_elements
[elem_count
];
2571 const Base_Type
* elem_value
= match_rec
->get_at(elem_count
);
2573 if (elem_value
->ispresent()) {
2574 if (!elem_tmpl
->matchv(elem_value
->get_opt_value(), legacy
)) {
2575 TTCN_Logger::log_logmatch_info(".%s", fld_name(elem_count
));
2576 elem_tmpl
->log_matchv(elem_value
->get_opt_value(), legacy
);
2577 TTCN_Logger::set_logmatch_buffer_len(previous_size
);
2580 if (!elem_tmpl
->match_omit(legacy
)) {
2581 TTCN_Logger::log_logmatch_info(".%s := omit with ", fld_name(elem_count
));
2582 TTCN_Logger::print_logmatch_buffer();
2584 TTCN_Logger::log_event_str(" unmatched");
2585 TTCN_Logger::set_logmatch_buffer_len(previous_size
);
2589 if (!elem_tmpl
->matchv(elem_value
, legacy
)) {
2590 TTCN_Logger::log_logmatch_info(".%s", fld_name(elem_count
));
2591 elem_tmpl
->log_matchv(elem_value
, legacy
);
2592 TTCN_Logger::set_logmatch_buffer_len(previous_size
);
2595 if (is_optional
) next_optional_idx
++;
2598 TTCN_Logger::print_logmatch_buffer();
2600 TTCN_Logger::log_event_str(" with ");
2602 TTCN_Logger::log_event_str(" unmatched");
2606 if (template_selection
== SPECIFIC_VALUE
) {
2607 const Record_Type
* match_rec
= static_cast<const Record_Type
*>(match_value
);
2608 const int* optional_indexes
= match_rec
->get_optional_indexes();
2609 int next_optional_idx
= 0;
2610 TTCN_Logger::log_event_str("{ ");
2611 for (int elem_count
= 0; elem_count
< single_value
.n_elements
; elem_count
++) {
2612 boolean is_optional
= optional_indexes
&& (optional_indexes
[next_optional_idx
]==elem_count
);
2613 const Base_Template
* elem_tmpl
= single_value
.value_elements
[elem_count
];
2614 const Base_Type
* elem_value
= match_rec
->get_at(elem_count
);
2615 if (elem_count
) TTCN_Logger::log_event_str(", ");
2616 TTCN_Logger::log_event_str(fld_name(elem_count
));
2617 TTCN_Logger::log_event_str(" := ");
2619 if (elem_value
->ispresent()) elem_tmpl
->log_matchv(elem_value
->get_opt_value(), legacy
);
2621 TTCN_Logger::log_event_str("omit with ");
2623 if (elem_tmpl
->match_omit(legacy
)) TTCN_Logger::log_event_str(" matched");
2624 else TTCN_Logger::log_event_str(" unmatched");
2627 elem_tmpl
->log_matchv(elem_value
, legacy
);
2629 if (is_optional
) next_optional_idx
++;
2631 TTCN_Logger::log_event_str(" }");
2634 TTCN_Logger::log_event_str(" with ");
2636 if (matchv(match_value
, legacy
)) TTCN_Logger::log_event_str(" matched");
2637 else TTCN_Logger::log_event_str(" unmatched");
2642 void Record_Template::encode_text(Text_Buf
& text_buf
) const
2644 encode_text_base(text_buf
);
2645 switch (template_selection
) {
2646 case SPECIFIC_VALUE
:
2647 for (int elem_count
= 0; elem_count
< single_value
.n_elements
; elem_count
++)
2648 single_value
.value_elements
[elem_count
]->encode_text(text_buf
);
2655 case COMPLEMENTED_LIST
:
2656 text_buf
.push_int(value_list
.n_values
);
2657 for (int list_count
= 0; list_count
< value_list
.n_values
; list_count
++)
2658 value_list
.list_value
[list_count
]->encode_text(text_buf
);
2661 TTCN_error("Text encoder: Encoding an uninitialized/unsupported template"
2662 " of type %s.", get_descriptor()->name
);
2666 void Record_Template::decode_text(Text_Buf
& text_buf
)
2669 decode_text_base(text_buf
);
2670 switch (template_selection
) {
2671 case SPECIFIC_VALUE
:
2672 template_selection
= UNINITIALIZED_TEMPLATE
; //set_specific will set it
2674 for (int elem_count
= 0; elem_count
< single_value
.n_elements
; elem_count
++)
2675 single_value
.value_elements
[elem_count
]->decode_text(text_buf
);
2682 case COMPLEMENTED_LIST
:
2683 value_list
.n_values
= text_buf
.pull_int().get_val();
2684 value_list
.list_value
= (Record_Template
**)allocate_pointers(value_list
.n_values
);
2685 for (int list_count
= 0; list_count
< value_list
.n_values
; list_count
++) {
2686 value_list
.list_value
[list_count
] = create();
2687 value_list
.list_value
[list_count
]->decode_text(text_buf
);
2691 TTCN_error("Text decoder: An unknown/unsupported selection was received in a template of type %s.", get_descriptor()->name
);
2695 boolean
Record_Template::is_present(boolean legacy
/*= FALSE*/) const
2697 if (template_selection
==UNINITIALIZED_TEMPLATE
) return FALSE
;
2698 return !match_omit(legacy
);
2701 boolean
Record_Template::match_omit(boolean legacy
/*= FALSE*/) const
2703 if (is_ifpresent
) return TRUE
;
2704 switch (template_selection
) {
2709 case COMPLEMENTED_LIST
:
2711 // legacy behavior: 'omit' can appear in the value/complement list
2712 for (int i
=0; i
<value_list
.n_values
; i
++)
2713 if (value_list
.list_value
[i
]->match_omit()) return template_selection
==VALUE_LIST
;
2714 return template_selection
==COMPLEMENTED_LIST
;
2716 // else fall through
2723 void Record_Template::set_param(Module_Param
& param
)
2725 if (dynamic_cast<Module_Param_Name
*>(param
.get_id()) != NULL
&&
2726 param
.get_id()->next_name()) {
2727 // Haven't reached the end of the module parameter name
2728 // => the name refers to one of the fields, not to the whole record
2729 char* param_field
= param
.get_id()->get_current_name();
2730 if (param_field
[0] >= '0' && param_field
[0] <= '9') {
2731 param
.error("Unexpected array index in module parameter, expected a valid field"
2732 " name for record/set template type `%s'", get_descriptor()->name
);
2735 for (int field_idx
= 0; field_idx
< single_value
.n_elements
; field_idx
++) {
2736 if (strcmp(fld_name(field_idx
), param_field
) == 0) {
2737 single_value
.value_elements
[field_idx
]->set_param(param
);
2741 param
.error("Field `%s' not found in record/set template type `%s'",
2742 param_field
, get_descriptor()->name
);
2745 param
.basic_check(Module_Param::BC_TEMPLATE
, "record/set template");
2747 Module_Param_Ptr mp
= ¶m
;
2748 if (param
.get_type() == Module_Param::MP_Reference
) {
2749 mp
= param
.get_referenced_param();
2752 switch (mp
->get_type()) {
2753 case Module_Param::MP_Omit
:
2754 set_value(OMIT_VALUE
);
2756 case Module_Param::MP_Any
:
2757 set_value(ANY_VALUE
);
2759 case Module_Param::MP_AnyOrNone
:
2760 set_value(ANY_OR_OMIT
);
2762 case Module_Param::MP_List_Template
:
2763 case Module_Param::MP_ComplementList_Template
: {
2764 Record_Template
** list_items
= (Record_Template
**)
2765 allocate_pointers(mp
->get_size());
2766 for (size_t i
= 0; i
< mp
->get_size(); i
++) {
2767 list_items
[i
] = create();
2768 list_items
[i
]->set_param(*mp
->get_elem(i
));
2771 template_selection
= mp
->get_type() == Module_Param::MP_List_Template
?
2772 VALUE_LIST
: COMPLEMENTED_LIST
;
2773 value_list
.n_values
= mp
->get_size();
2774 value_list
.list_value
= list_items
;
2776 case Module_Param::MP_Value_List
:
2778 if (single_value
.n_elements
<(int)mp
->get_size()) {
2779 param
.error("Record/set template of type %s has %d fields but list value has %d fields", get_descriptor()->name
, single_value
.n_elements
, (int)mp
->get_size());
2781 for (size_t i
=0; i
<mp
->get_size(); i
++) {
2782 Module_Param
* mp_field
= mp
->get_elem(i
);
2783 if (mp_field
->get_type()!=Module_Param::MP_NotUsed
) {
2784 get_at((int)i
)->set_param(*mp_field
);
2788 case Module_Param::MP_Assignment_List
:
2790 for (size_t i
=0; i
<mp
->get_size(); ++i
) {
2791 Module_Param
* const current
= mp
->get_elem(i
);
2793 for (int j
=0; j
<single_value
.n_elements
; ++j
) {
2794 if (!strcmp(fld_name(j
), current
->get_id()->get_name())) {
2795 if (current
->get_type()!=Module_Param::MP_NotUsed
) {
2796 get_at(j
)->set_param(*current
);
2803 current
->error("Non existent field name in type %s: %s.", get_descriptor()->name
, current
->get_id()->get_name());
2808 param
.type_error("record/set template", get_descriptor()->name
);
2810 is_ifpresent
= param
.get_ifpresent() || mp
->get_ifpresent();
2813 Module_Param
* Record_Template::get_param(Module_Param_Name
& param_name
) const
2815 if (param_name
.next_name()) {
2816 // Haven't reached the end of the module parameter name
2817 // => the name refers to one of the fields, not to the whole record
2818 char* param_field
= param_name
.get_current_name();
2819 if (param_field
[0] >= '0' && param_field
[0] <= '9') {
2820 TTCN_error("Unexpected array index in module parameter reference, "
2821 "expected a valid field name for record/set template type `%s'",
2822 get_descriptor()->name
);
2824 for (int field_idx
= 0; field_idx
< single_value
.n_elements
; field_idx
++) {
2825 if (strcmp(fld_name(field_idx
), param_field
) == 0) {
2826 return get_at(field_idx
)->get_param(param_name
);
2829 TTCN_error("Field `%s' not found in record/set type `%s'",
2830 param_field
, get_descriptor()->name
);
2832 Module_Param
* mp
= NULL
;
2833 switch (template_selection
) {
2834 case UNINITIALIZED_TEMPLATE
:
2835 mp
= new Module_Param_Unbound();
2838 mp
= new Module_Param_Omit();
2841 mp
= new Module_Param_Any();
2844 mp
= new Module_Param_AnyOrNone();
2846 case SPECIFIC_VALUE
: {
2847 mp
= new Module_Param_Assignment_List();
2848 for (int i
= 0; i
< single_value
.n_elements
; ++i
) {
2849 Module_Param
* mp_field
= get_at(i
)->get_param(param_name
);
2850 mp_field
->set_id(new Module_Param_FieldName(mcopystr(fld_name(i
))));
2851 mp
->add_elem(mp_field
);
2855 case COMPLEMENTED_LIST
: {
2856 if (template_selection
== VALUE_LIST
) {
2857 mp
= new Module_Param_List_Template();
2860 mp
= new Module_Param_ComplementList_Template();
2862 for (int i
= 0; i
< value_list
.n_values
; ++i
) {
2863 mp
->add_elem(value_list
.list_value
[i
]->get_param(param_name
));
2870 mp
->set_ifpresent();
2875 void Record_Template::check_restriction(template_res t_res
, const char* t_name
,
2876 boolean legacy
/* = FALSE */) const
2878 if (template_selection
==UNINITIALIZED_TEMPLATE
) return;
2879 switch ((t_name
&&(t_res
==TR_VALUE
))?TR_OMIT
:t_res
) {
2881 if (template_selection
==OMIT_VALUE
) return;
2884 if (template_selection
!=SPECIFIC_VALUE
|| is_ifpresent
) break;
2885 for (int i
=0; i
<single_value
.n_elements
; i
++)
2886 single_value
.value_elements
[i
]->check_restriction(t_res
, t_name
? t_name
: get_descriptor()->name
);
2889 if (!match_omit(legacy
)) return;
2894 TTCN_error("Restriction `%s' on template of type %s violated.",
2895 get_res_name(t_res
), t_name
? t_name
: get_descriptor()->name
);
2898 ////////////////////////////////////////////////////////////////////////////////
2900 Empty_Record_Template::Empty_Record_Template(): Base_Template()
2904 Empty_Record_Template::Empty_Record_Template(template_sel other_value
):
2905 Base_Template(other_value
)
2907 check_single_selection(other_value
);
2910 Empty_Record_Template::~Empty_Record_Template()
2915 void Empty_Record_Template::clean_up()
2917 switch (template_selection
) {
2919 case COMPLEMENTED_LIST
:
2920 for (int elem_count
= 0; elem_count
< value_list
.n_values
; elem_count
++)
2921 delete value_list
.list_value
[elem_count
];
2922 free_pointers((void**)value_list
.list_value
);
2927 template_selection
= UNINITIALIZED_TEMPLATE
;
2930 void Empty_Record_Template::copy_value(const Base_Type
* other_value
)
2932 if (!other_value
->is_bound())
2933 TTCN_error("Initialization of a record/set template with an unbound value.");
2934 set_selection(SPECIFIC_VALUE
);
2937 void Empty_Record_Template::copy_template(const Empty_Record_Template
& other_value
)
2939 switch (other_value
.template_selection
) {
2940 case SPECIFIC_VALUE
:
2946 case COMPLEMENTED_LIST
:
2947 value_list
.n_values
= other_value
.value_list
.n_values
;
2948 value_list
.list_value
= (Empty_Record_Template
**)allocate_pointers(value_list
.n_values
);
2949 for (int list_count
= 0; list_count
< value_list
.n_values
; list_count
++)
2950 value_list
.list_value
[list_count
] = static_cast<Empty_Record_Template
*>(other_value
.value_list
.list_value
[list_count
]->clone());
2953 TTCN_error("Copying an uninitialized/unsupported record/set template.");
2956 set_selection(other_value
);
2959 void Empty_Record_Template::copy_optional(const Base_Type
* other_value
)
2961 if (other_value
->is_present()) {
2962 const Empty_Record_Type
* other_rec
= static_cast<const Empty_Record_Type
*>(other_value
->get_opt_value());
2963 copy_value(other_rec
);
2964 } else if (other_value
->is_bound()) {
2965 set_selection(OMIT_VALUE
);
2967 TTCN_error("Initialization of a record/set template with an unbound optional field.");
2971 void Empty_Record_Template::set_type(template_sel template_type
, int list_length
)
2973 if (template_type
!= VALUE_LIST
&& template_type
!= COMPLEMENTED_LIST
)
2974 TTCN_error("Setting an invalid list for a template of type %s.", get_descriptor()->name
);
2976 set_selection(template_type
);
2977 value_list
.n_values
= list_length
;
2978 value_list
.list_value
= (Empty_Record_Template
**)allocate_pointers(value_list
.n_values
);
2979 for (int list_count
= 0; list_count
< value_list
.n_values
; list_count
++)
2980 value_list
.list_value
[list_count
] = create();
2983 Empty_Record_Template
* Empty_Record_Template::get_list_item(int list_index
) const
2985 if (template_selection
!= VALUE_LIST
&& template_selection
!= COMPLEMENTED_LIST
)
2986 TTCN_error("Accessing a list element of a non-list template of type %s.", get_descriptor()->name
);
2987 if (list_index
>= value_list
.n_values
|| list_index
< 0)
2988 TTCN_error("Index overflow in a value list template of type %s.", get_descriptor()->name
);
2989 return value_list
.list_value
[list_index
];
2992 int Empty_Record_Template::size_of() const
2995 TTCN_error("Performing sizeof() operation on a template of type %s "
2996 "which has an ifpresent attribute.", get_descriptor()->name
);
2997 switch (template_selection
)
2999 case SPECIFIC_VALUE
:
3002 if (value_list
.n_values
<1)
3003 TTCN_error("Internal error: Performing sizeof() operation on a template of type %s containing an empty list.", get_descriptor()->name
);
3004 int item_size
= value_list
.list_value
[0]->size_of();
3005 for (int i
= 1; i
< value_list
.n_values
; i
++)
3006 if (value_list
.list_value
[i
]->size_of()!=item_size
)
3007 TTCN_error("Performing sizeof() operation on a template of type %s containing a value list with different sizes.", get_descriptor()->name
);
3011 TTCN_error("Performing sizeof() operation on a template of type %s containing omit value.", get_descriptor()->name
);
3014 TTCN_error("Performing sizeof() operation on a template of type %s containing */? value.", get_descriptor()->name
);
3015 case COMPLEMENTED_LIST
:
3016 TTCN_error("Performing sizeof() operation on a template of type %s containing complemented list.", get_descriptor()->name
);
3018 TTCN_error("Performing sizeof() operation on an uninitialized/unsupported template of type %s.", get_descriptor()->name
);
3023 boolean
Empty_Record_Template::is_value() const
3025 return (template_selection
== SPECIFIC_VALUE
&& !is_ifpresent
);
3028 void Empty_Record_Template::valueofv(Base_Type
* value
) const
3030 if (template_selection
!= SPECIFIC_VALUE
|| is_ifpresent
)
3031 TTCN_error("Performing a valueof or send operation on a non-specific template of type %s.", get_descriptor()->name
);
3032 Empty_Record_Type
* rec_value
= static_cast<Empty_Record_Type
*>(value
);
3033 rec_value
->set_null();
3036 void Empty_Record_Template::set_value(template_sel other_value
)
3038 check_single_selection(other_value
);
3040 set_selection(other_value
);
3043 Base_Template
* Empty_Record_Template::clone() const
3045 Empty_Record_Template
* rec
= create();
3046 rec
->copy_template(*this);
3050 void Empty_Record_Template::log() const
3052 switch (template_selection
) {
3053 case SPECIFIC_VALUE
:
3054 TTCN_Logger::log_event_str("{ }");
3056 case COMPLEMENTED_LIST
:
3057 TTCN_Logger::log_event_str("complement ");
3060 TTCN_Logger::log_char('(');
3061 for (int list_count
= 0; list_count
< value_list
.n_values
; list_count
++) {
3062 if (list_count
> 0) TTCN_Logger::log_event_str(", ");
3063 value_list
.list_value
[list_count
]->log();
3065 TTCN_Logger::log_char(')');
3074 boolean
Empty_Record_Template::matchv(const Base_Type
* other_value
,
3075 boolean legacy
) const
3077 switch (template_selection
) {
3083 case SPECIFIC_VALUE
:
3086 case COMPLEMENTED_LIST
:
3087 for (int list_count
= 0; list_count
< value_list
.n_values
; list_count
++)
3088 if (value_list
.list_value
[list_count
]->matchv(other_value
, legacy
)) return template_selection
== VALUE_LIST
;
3089 return template_selection
== COMPLEMENTED_LIST
;
3091 TTCN_error("Matching an uninitialized/unsupported template of type %s.", get_descriptor()->name
);
3096 void Empty_Record_Template::log_matchv(const Base_Type
* match_value
, boolean legacy
) const
3099 TTCN_Logger::log_event_str(" with ");
3101 if (matchv(match_value
, legacy
)) TTCN_Logger::log_event_str(" matched");
3102 else TTCN_Logger::log_event_str(" unmatched");
3105 void Empty_Record_Template::encode_text(Text_Buf
& text_buf
) const
3107 encode_text_base(text_buf
);
3108 switch (template_selection
) {
3109 case SPECIFIC_VALUE
:
3115 case COMPLEMENTED_LIST
:
3116 text_buf
.push_int(value_list
.n_values
);
3117 for (int list_count
= 0; list_count
< value_list
.n_values
; list_count
++)
3118 value_list
.list_value
[list_count
]->encode_text(text_buf
);
3121 TTCN_error("Text encoder: Encoding an uninitialized/unsupported template of type %s.", get_descriptor()->name
);
3125 void Empty_Record_Template::decode_text(Text_Buf
& text_buf
)
3128 decode_text_base(text_buf
);
3129 switch (template_selection
) {
3130 case SPECIFIC_VALUE
:
3136 case COMPLEMENTED_LIST
:
3137 value_list
.n_values
= text_buf
.pull_int().get_val();
3138 value_list
.list_value
= (Empty_Record_Template
**)allocate_pointers(value_list
.n_values
);
3139 for (int list_count
= 0; list_count
< value_list
.n_values
; list_count
++) {
3140 value_list
.list_value
[list_count
] = create();
3141 value_list
.list_value
[list_count
]->decode_text(text_buf
);
3145 TTCN_error("Text decoder: An unknown/unsupported selection was received in a template of type %s.", get_descriptor()->name
);
3149 boolean
Empty_Record_Template::is_present(boolean legacy
/*= FALSE*/) const
3151 if (template_selection
==UNINITIALIZED_TEMPLATE
) return FALSE
;
3152 return !match_omit(legacy
);
3155 boolean
Empty_Record_Template::match_omit(boolean legacy
/* = FALSE */) const
3157 if (is_ifpresent
) return TRUE
;
3158 switch (template_selection
) {
3163 case COMPLEMENTED_LIST
:
3165 // legacy behavior: 'omit' can appear in the value/complement list
3166 for (int i
=0; i
<value_list
.n_values
; i
++)
3167 if (value_list
.list_value
[i
]->match_omit()) return template_selection
==VALUE_LIST
;
3168 return template_selection
==COMPLEMENTED_LIST
;
3170 // else fall through
3177 void Empty_Record_Template::set_param(Module_Param
& param
)
3179 param
.basic_check(Module_Param::BC_TEMPLATE
, "empty record/set template");
3180 Module_Param_Ptr mp
= ¶m
;
3181 if (param
.get_type() == Module_Param::MP_Reference
) {
3182 mp
= param
.get_referenced_param();
3184 switch (mp
->get_type()) {
3185 case Module_Param::MP_Omit
:
3186 set_value(OMIT_VALUE
);
3188 case Module_Param::MP_Any
:
3189 set_value(ANY_VALUE
);
3191 case Module_Param::MP_AnyOrNone
:
3192 set_value(ANY_OR_OMIT
);
3194 case Module_Param::MP_List_Template
:
3195 case Module_Param::MP_ComplementList_Template
: {
3196 Empty_Record_Template
** list_items
= (Empty_Record_Template
**)
3197 allocate_pointers(mp
->get_size());
3198 for (size_t i
= 0; i
< mp
->get_size(); i
++) {
3199 list_items
[i
] = create();
3200 list_items
[i
]->set_param(*mp
->get_elem(i
));
3203 template_selection
= mp
->get_type() == Module_Param::MP_List_Template
?
3204 VALUE_LIST
: COMPLEMENTED_LIST
;
3205 value_list
.n_values
= mp
->get_size();
3206 value_list
.list_value
= list_items
;
3208 case Module_Param::MP_Value_List
:
3209 if (mp
->get_size()==0) {
3210 set_selection(SPECIFIC_VALUE
);
3212 else param
.type_error("empty record/set template", get_descriptor()->name
);
3215 param
.type_error("empty record/set template", get_descriptor()->name
);
3217 is_ifpresent
= param
.get_ifpresent() || mp
->get_ifpresent();
3220 Module_Param
* Empty_Record_Template::get_param(Module_Param_Name
& param_name
) const
3222 Module_Param
* mp
= NULL
;
3223 switch (template_selection
) {
3224 case UNINITIALIZED_TEMPLATE
:
3225 mp
= new Module_Param_Unbound();
3228 mp
= new Module_Param_Omit();
3231 mp
= new Module_Param_Any();
3234 mp
= new Module_Param_AnyOrNone();
3236 case SPECIFIC_VALUE
:
3237 mp
= new Module_Param_Value_List();
3240 case COMPLEMENTED_LIST
: {
3241 if (template_selection
== VALUE_LIST
) {
3242 mp
= new Module_Param_List_Template();
3245 mp
= new Module_Param_ComplementList_Template();
3247 for (int i
= 0; i
< value_list
.n_values
; ++i
) {
3248 mp
->add_elem(value_list
.list_value
[i
]->get_param(param_name
));
3255 mp
->set_ifpresent();