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
:
979 TTCN_error("Performing n_elem() operation on an uninitialized/unsupported "
980 "template of type %s.", get_descriptor()->name
);
983 boolean
Record_Of_Template::matchv(const Base_Type
* other_value
,
984 boolean legacy
) const
986 const Record_Of_Type
* other_recof
= static_cast<const Record_Of_Type
*>(other_value
);
987 if (!other_value
->is_bound()) return FALSE
;
988 int value_length
= other_recof
->size_of();
989 if (!match_length(value_length
)) return FALSE
;
990 switch (template_selection
) {
992 return match_record_of(other_recof
, value_length
, this,
993 single_value
.n_elements
, match_function_specific
, legacy
);
1000 case COMPLEMENTED_LIST
:
1001 for (int list_count
= 0; list_count
< value_list
.n_values
; list_count
++)
1002 if (value_list
.list_value
[list_count
]->matchv(other_value
, legacy
))
1003 return template_selection
== VALUE_LIST
;
1004 return template_selection
== COMPLEMENTED_LIST
;
1006 TTCN_error("Matching with an uninitialized/unsupported template of type %s.",
1007 get_descriptor()->name
);
1012 boolean
Record_Of_Template::is_value() const
1014 if (template_selection
!= SPECIFIC_VALUE
|| is_ifpresent
) return FALSE
;
1015 for (int elem_count
= 0; elem_count
< single_value
.n_elements
; elem_count
++)
1016 if (!single_value
.value_elements
[elem_count
]->is_value()) return FALSE
;
1020 void Record_Of_Template::set_type(template_sel template_type
, int list_length
)
1023 switch (template_type
) {
1025 case COMPLEMENTED_LIST
:
1026 value_list
.n_values
= list_length
;
1027 value_list
.list_value
= (Record_Of_Template
**)allocate_pointers(value_list
.n_values
);
1028 for (int list_count
= 0; list_count
< value_list
.n_values
; list_count
++)
1029 value_list
.list_value
[list_count
] = create();
1032 TTCN_error("Internal error: Setting an invalid type for a template of "
1033 "type %s.", get_descriptor()->name
);
1035 set_selection(template_type
);
1038 Record_Of_Template
* Record_Of_Template::get_list_item(int list_index
)
1040 if (template_selection
!= VALUE_LIST
&& template_selection
!= COMPLEMENTED_LIST
)
1041 TTCN_error("Internal error: Accessing a list element of a non-list "
1042 "template of type %s.", get_descriptor()->name
);
1043 if (list_index
>= value_list
.n_values
|| list_index
< 0)
1044 TTCN_error("Internal error: Index overflow in a value list template "
1045 "of type %s.", get_descriptor()->name
);
1046 return value_list
.list_value
[list_index
];
1049 void Record_Of_Template::log() const
1051 switch (template_selection
) {
1052 case SPECIFIC_VALUE
:
1053 if (single_value
.n_elements
> 0) {
1054 TTCN_Logger::log_event_str("{ ");
1055 for (int elem_count
= 0; elem_count
< single_value
.n_elements
; elem_count
++) {
1056 if (elem_count
> 0) TTCN_Logger::log_event_str(", ");
1057 if (permutation_starts_at(elem_count
)) TTCN_Logger::log_event_str("permutation(");
1058 single_value
.value_elements
[elem_count
]->log();
1059 if (permutation_ends_at(elem_count
)) TTCN_Logger::log_char(')');
1061 TTCN_Logger::log_event_str(" }");
1062 } else TTCN_Logger::log_event_str("{ }");
1064 case COMPLEMENTED_LIST
:
1065 TTCN_Logger::log_event_str("complement ");
1068 TTCN_Logger::log_char('(');
1069 for (int list_count
= 0; list_count
< value_list
.n_values
; list_count
++) {
1070 if (list_count
> 0) TTCN_Logger::log_event_str(", ");
1071 value_list
.list_value
[list_count
]->log();
1073 TTCN_Logger::log_char(')');
1081 if (err_descr
) err_descr
->log();
1084 void Record_Of_Template::log_matchv(const Base_Type
* match_value
, boolean legacy
) const
1086 if (TTCN_Logger::VERBOSITY_COMPACT
== TTCN_Logger::get_matching_verbosity()) {
1087 if (matchv(match_value
, legacy
)) {
1088 TTCN_Logger::print_logmatch_buffer();
1089 TTCN_Logger::log_event_str(" matched");
1091 const Record_Of_Type
* recof_value
= static_cast<const Record_Of_Type
*>(match_value
);
1092 if (template_selection
== SPECIFIC_VALUE
&&
1093 single_value
.n_elements
> 0 && get_number_of_permutations() == 0 &&
1094 single_value
.n_elements
== recof_value
->size_of()) {
1095 size_t previous_size
= TTCN_Logger::get_logmatch_buffer_len();
1096 for (int elem_count
= 0; elem_count
< single_value
.n_elements
; elem_count
++) {
1097 if(!single_value
.value_elements
[elem_count
]->matchv(recof_value
->get_at(elem_count
), legacy
)){
1098 TTCN_Logger::log_logmatch_info("[%d]", elem_count
);
1099 single_value
.value_elements
[elem_count
]->log_matchv(recof_value
->get_at(elem_count
), legacy
);
1100 TTCN_Logger::set_logmatch_buffer_len(previous_size
);
1103 log_match_length(single_value
.n_elements
);
1105 TTCN_Logger::print_logmatch_buffer();
1107 TTCN_Logger::log_event_str(" with ");
1109 TTCN_Logger::log_event_str(" unmatched");
1113 const Record_Of_Type
* recof_value
= static_cast<const Record_Of_Type
*>(match_value
);
1114 if (template_selection
== SPECIFIC_VALUE
&&
1115 single_value
.n_elements
> 0 && get_number_of_permutations() == 0 &&
1116 single_value
.n_elements
== recof_value
->size_of()) {
1117 TTCN_Logger::log_event_str("{ ");
1118 for (int elem_count
= 0; elem_count
< single_value
.n_elements
; elem_count
++) {
1119 if (elem_count
> 0) TTCN_Logger::log_event_str(", ");
1120 single_value
.value_elements
[elem_count
]->log_matchv(recof_value
->get_at(elem_count
), legacy
);
1122 TTCN_Logger::log_event_str(" }");
1123 log_match_length(single_value
.n_elements
);
1126 TTCN_Logger::log_event_str(" with ");
1128 if (matchv(match_value
, legacy
)) TTCN_Logger::log_event_str(" matched");
1129 else TTCN_Logger::log_event_str(" unmatched");
1134 void Record_Of_Template::encode_text(Text_Buf
& text_buf
) const
1136 encode_text_permutation(text_buf
);
1137 switch (template_selection
) {
1138 case SPECIFIC_VALUE
:
1139 text_buf
.push_int(single_value
.n_elements
);
1140 for (int elem_count
= 0; elem_count
< single_value
.n_elements
; elem_count
++)
1141 single_value
.value_elements
[elem_count
]->encode_text(text_buf
);
1148 case COMPLEMENTED_LIST
:
1149 text_buf
.push_int(value_list
.n_values
);
1150 for (int list_count
= 0; list_count
< value_list
.n_values
; list_count
++)
1151 value_list
.list_value
[list_count
]->encode_text(text_buf
);
1154 TTCN_error("Text encoder: Encoding an uninitialized/unsupported template "
1155 "of type %s.", get_descriptor()->name
);
1159 void Record_Of_Template::decode_text(Text_Buf
& text_buf
)
1162 decode_text_permutation(text_buf
);
1163 switch (template_selection
) {
1164 case SPECIFIC_VALUE
:
1165 single_value
.n_elements
= text_buf
.pull_int().get_val();
1166 if (single_value
.n_elements
< 0)
1167 TTCN_error("Text decoder: Negative size was received for a template of "
1168 "type %s.", get_descriptor()->name
);
1169 single_value
.value_elements
= (Base_Template
**)allocate_pointers(single_value
.n_elements
);
1170 for (int elem_count
= 0; elem_count
< single_value
.n_elements
; elem_count
++) {
1171 single_value
.value_elements
[elem_count
] = create_elem();
1172 single_value
.value_elements
[elem_count
]->decode_text(text_buf
);
1180 case COMPLEMENTED_LIST
:
1181 value_list
.n_values
= text_buf
.pull_int().get_val();
1182 value_list
.list_value
= (Record_Of_Template
**)allocate_pointers(value_list
.n_values
);
1183 for (int list_count
= 0; list_count
< value_list
.n_values
; list_count
++) {
1184 value_list
.list_value
[list_count
] = create();
1185 value_list
.list_value
[list_count
]->decode_text(text_buf
);
1189 TTCN_error("Text decoder: An unknown/unsupported selection was received "
1190 "for a template of type %s.", get_descriptor()->name
);
1194 boolean
Record_Of_Template::is_present(boolean legacy
/* = FALSE */) const
1196 if (template_selection
==UNINITIALIZED_TEMPLATE
) return FALSE
;
1197 return !match_omit(legacy
);
1200 boolean
Record_Of_Template::match_omit(boolean legacy
/* = FALSE */) const
1202 if (is_ifpresent
) return TRUE
;
1203 switch (template_selection
) {
1208 case COMPLEMENTED_LIST
:
1210 // legacy behavior: 'omit' can appear in the value/complement list
1211 for (int i
=0; i
<value_list
.n_values
; i
++)
1212 if (value_list
.list_value
[i
]->match_omit())
1213 return template_selection
==VALUE_LIST
;
1214 return template_selection
==COMPLEMENTED_LIST
;
1216 // else fall through
1223 void Record_Of_Template::set_param(Module_Param
& param
)
1225 if (dynamic_cast<Module_Param_Name
*>(param
.get_id()) != NULL
&&
1226 param
.get_id()->next_name()) {
1227 // Haven't reached the end of the module parameter name
1228 // => the name refers to one of the elements, not to the whole record of
1229 char* param_field
= param
.get_id()->get_current_name();
1230 if (param_field
[0] < '0' || param_field
[0] > '9') {
1231 param
.error("Unexpected record field name in module parameter, expected a valid"
1232 " index for record of template type `%s'", get_descriptor()->name
);
1234 int param_index
= -1;
1235 sscanf(param_field
, "%d", ¶m_index
);
1236 get_at(param_index
)->set_param(param
);
1240 param
.basic_check(Module_Param::BC_TEMPLATE
|Module_Param::BC_LIST
, "record of template");
1242 Module_Param_Ptr mp
= ¶m
;
1243 if (param
.get_type() == Module_Param::MP_Reference
) {
1244 mp
= param
.get_referenced_param();
1247 switch (mp
->get_type()) {
1248 case Module_Param::MP_Omit
:
1249 set_value(OMIT_VALUE
);
1251 case Module_Param::MP_Any
:
1252 set_value(ANY_VALUE
);
1254 case Module_Param::MP_AnyOrNone
:
1255 set_value(ANY_OR_OMIT
);
1257 case Module_Param::MP_List_Template
:
1258 case Module_Param::MP_ComplementList_Template
: {
1259 Record_Of_Template
** list_items
= (Record_Of_Template
**)
1260 allocate_pointers(mp
->get_size());
1261 for (size_t i
= 0; i
< mp
->get_size(); i
++) {
1262 list_items
[i
] = create();
1263 list_items
[i
]->set_param(*mp
->get_elem(i
));
1266 template_selection
= mp
->get_type() == Module_Param::MP_List_Template
?
1267 VALUE_LIST
: COMPLEMENTED_LIST
;
1268 value_list
.n_values
= mp
->get_size();
1269 value_list
.list_value
= list_items
;
1271 case Module_Param::MP_Value_List
: {
1272 set_size(mp
->get_size()); // at least this size if there are no permutation elements, if there are then get_at() will automatically resize
1273 int curr_idx
= 0; // current index into this
1274 for (size_t i
=0; i
<mp
->get_size(); ++i
) {
1275 Module_Param
* const curr
= mp
->get_elem(i
);
1276 switch (curr
->get_type()) {
1277 case Module_Param::MP_NotUsed
:
1278 // skip this element
1281 case Module_Param::MP_Permutation_Template
: {
1282 // insert all elements from the permutation
1283 int perm_start_idx
= curr_idx
;
1284 for (size_t perm_i
=0; perm_i
<curr
->get_size(); perm_i
++) {
1285 get_at(curr_idx
)->set_param(*(curr
->get_elem(perm_i
)));
1288 int perm_end_idx
= curr_idx
- 1;
1289 add_permutation(perm_start_idx
, perm_end_idx
);
1292 get_at(curr_idx
)->set_param(*curr
);
1297 case Module_Param::MP_Indexed_List
:
1298 if (template_selection
!=SPECIFIC_VALUE
) set_size(0);
1299 for (size_t i
=0; i
<mp
->get_size(); ++i
) {
1300 Module_Param
* const current
= mp
->get_elem(i
);
1301 get_at((int)current
->get_id()->get_index())->set_param(*current
);
1305 param
.type_error("record of template", get_descriptor()->name
);
1307 is_ifpresent
= param
.get_ifpresent() || mp
->get_ifpresent();
1308 if (param
.get_length_restriction() != NULL
) {
1309 set_length_range(param
);
1312 set_length_range(*mp
);
1316 Module_Param
* Record_Of_Template::get_param(Module_Param_Name
& param_name
) const
1318 if (param_name
.next_name()) {
1319 // Haven't reached the end of the module parameter name
1320 // => the name refers to one of the elements, not to the whole record of
1321 char* param_field
= param_name
.get_current_name();
1322 if (param_field
[0] < '0' || param_field
[0] > '9') {
1323 TTCN_error("Unexpected record field name in module parameter reference, "
1324 "expected a valid index for record of template type `%s'",
1325 get_descriptor()->name
);
1327 int param_index
= -1;
1328 sscanf(param_field
, "%d", ¶m_index
);
1329 return get_at(param_index
)->get_param(param_name
);
1331 Module_Param
* mp
= NULL
;
1332 switch (template_selection
) {
1333 case UNINITIALIZED_TEMPLATE
:
1334 mp
= new Module_Param_Unbound();
1337 mp
= new Module_Param_Omit();
1340 mp
= new Module_Param_Any();
1343 mp
= new Module_Param_AnyOrNone();
1345 case SPECIFIC_VALUE
: {
1346 Vector
<Module_Param
*> values
;
1347 for (int i
= 0; i
< single_value
.n_elements
; ++i
) {
1348 values
.push_back(single_value
.value_elements
[i
]->get_param(param_name
));
1350 mp
= new Module_Param_Value_List();
1351 mp
->add_list_with_implicit_ids(&values
);
1355 case COMPLEMENTED_LIST
: {
1356 if (template_selection
== VALUE_LIST
) {
1357 mp
= new Module_Param_List_Template();
1360 mp
= new Module_Param_ComplementList_Template();
1362 for (int i
= 0; i
< value_list
.n_values
; ++i
) {
1363 mp
->add_elem(value_list
.list_value
[i
]->get_param(param_name
));
1370 mp
->set_ifpresent();
1372 mp
->set_length_restriction(get_length_range());
1376 void Record_Of_Template::check_restriction(template_res t_res
, const char* t_name
,
1377 boolean legacy
/* = FALSE */) const
1379 if (template_selection
==UNINITIALIZED_TEMPLATE
) return;
1380 switch ((t_name
&& (t_res
==TR_VALUE
)) ? TR_OMIT
: t_res
) {
1382 if (template_selection
==OMIT_VALUE
) return;
1385 if (template_selection
!=SPECIFIC_VALUE
|| is_ifpresent
) break;
1386 for (int i
=0; i
<single_value
.n_elements
; i
++)
1387 single_value
.value_elements
[i
]->check_restriction(t_res
, t_name
? t_name
: get_descriptor()->name
);
1390 if (!match_omit(legacy
)) return;
1395 TTCN_error("Restriction `%s' on template of type %s violated.",
1396 get_res_name(t_res
), t_name
? t_name
: get_descriptor()->name
);
1399 ////////////////////////////////////////////////////////////////////////////////
1401 void Set_Of_Template::substr_(int index
, int returncount
, Record_Of_Type
* rec_of
) const
1403 if (!is_value()) TTCN_error("The first argument of function substr() is a template of type %s with non-specific value.", get_descriptor()->name
);
1404 rec_of
->set_val(NULL_VALUE
);
1405 Base_Type
* this_value
= rec_of
->clone();
1406 valueofv(this_value
);
1407 static_cast<Record_Of_Type
*>(this_value
)->substr_(index
, returncount
, rec_of
);
1411 void Set_Of_Template::replace_(int index
, int len
,
1412 const Set_Of_Template
* repl
, Record_Of_Type
* rec_of
) const
1414 if (!is_value()) TTCN_error("The first argument of function replace() is a template of type %s with non-specific value.", get_descriptor()->name
);
1415 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
);
1416 rec_of
->set_val(NULL_VALUE
);
1417 Base_Type
* this_value
= rec_of
->clone();
1418 valueofv(this_value
);
1419 Base_Type
* repl_value
= rec_of
->clone();
1420 repl
->valueofv(repl_value
);
1421 // call the replace() function of the value class instance
1422 static_cast<Record_Of_Type
*>(this_value
)->replace_(index
, len
, static_cast<Record_Of_Type
*>(repl_value
), rec_of
);
1427 void Set_Of_Template::replace_(int index
, int len
,
1428 const Record_Of_Type
* repl
, Record_Of_Type
* rec_of
) const
1430 if (!is_value()) TTCN_error("The first argument of function replace() is a template of type %s with non-specific value.", get_descriptor()->name
);
1431 rec_of
->set_val(NULL_VALUE
);
1432 Base_Type
* this_value
= rec_of
->clone();
1433 valueofv(this_value
);
1434 // call the replace() function of the value class instance
1435 static_cast<Record_Of_Type
*>(this_value
)->replace_(index
, len
, repl
, rec_of
);
1439 Set_Of_Template::Set_Of_Template(): err_descr(NULL
)
1443 Set_Of_Template::Set_Of_Template(template_sel other_value
)
1444 : Restricted_Length_Template(other_value
), err_descr(NULL
)
1448 Set_Of_Template::~Set_Of_Template()
1453 void Set_Of_Template::clean_up()
1455 switch (template_selection
) {
1456 case SPECIFIC_VALUE
:
1457 case SUPERSET_MATCH
:
1459 for (int elem_count
= 0; elem_count
< single_value
.n_elements
; elem_count
++)
1460 delete single_value
.value_elements
[elem_count
];
1461 free_pointers((void**)single_value
.value_elements
);
1464 case COMPLEMENTED_LIST
:
1465 for (int elem_count
= 0; elem_count
< value_list
.n_values
; elem_count
++)
1466 delete value_list
.list_value
[elem_count
];
1467 free_pointers((void**)value_list
.list_value
);
1472 template_selection
= UNINITIALIZED_TEMPLATE
;
1475 void Set_Of_Template::copy_value(const Base_Type
* other_value
)
1477 if (!other_value
->is_bound())
1478 TTCN_error("Initialization of a set of template with an unbound value.");
1479 const Record_Of_Type
* other_setof
= static_cast<const Record_Of_Type
*>(other_value
);
1480 single_value
.n_elements
= other_setof
->size_of();
1481 single_value
.value_elements
= (Base_Template
**)allocate_pointers(single_value
.n_elements
);
1482 for (int elem_count
= 0; elem_count
< single_value
.n_elements
; elem_count
++) {
1483 single_value
.value_elements
[elem_count
] = create_elem();
1484 single_value
.value_elements
[elem_count
]->copy_value(other_setof
->get_at(elem_count
));
1486 set_selection(SPECIFIC_VALUE
);
1487 err_descr
= other_setof
->get_err_descr();
1490 void Set_Of_Template::copy_optional(const Base_Type
* other_value
)
1492 if (other_value
->is_present()) {
1493 const Record_Of_Type
* other_setof
= static_cast<const Record_Of_Type
*>(other_value
->get_opt_value());
1494 copy_value(other_setof
);
1495 } else if (other_value
->is_bound()) {
1496 set_selection(OMIT_VALUE
);
1499 TTCN_error("Initialization of a set of template with an unbound optional field.");
1503 void Set_Of_Template::copy_template(const Set_Of_Template
& other_value
)
1505 switch (other_value
.template_selection
) {
1506 case SPECIFIC_VALUE
:
1507 case SUPERSET_MATCH
:
1509 single_value
.n_elements
= other_value
.single_value
.n_elements
;
1510 single_value
.value_elements
= (Base_Template
**)allocate_pointers(single_value
.n_elements
);
1511 for (int elem_count
= 0; elem_count
< single_value
.n_elements
; elem_count
++)
1512 single_value
.value_elements
[elem_count
] = other_value
.single_value
.value_elements
[elem_count
]->clone();
1519 case COMPLEMENTED_LIST
:
1520 value_list
.n_values
= other_value
.value_list
.n_values
;
1521 value_list
.list_value
= (Set_Of_Template
**)allocate_pointers(value_list
.n_values
);
1522 for (int list_count
= 0; list_count
< value_list
.n_values
; list_count
++)
1523 value_list
.list_value
[list_count
] = static_cast<Set_Of_Template
*>(other_value
.value_list
.list_value
[list_count
]->clone());
1526 TTCN_error("Copying an uninitialized/unsupported set of template");
1529 set_selection(other_value
);
1530 err_descr
= other_value
.err_descr
;
1533 Base_Template
* Set_Of_Template::clone() const
1535 Set_Of_Template
* setof
= create();
1536 setof
->copy_template(*this);
1540 Base_Template
* Set_Of_Template::get_at(int index_value
)
1542 if (index_value
< 0)
1543 TTCN_error("Accessing an element of a template for type %s using a "
1544 "negative index: %d.", get_descriptor()->name
, index_value
);
1545 if (template_selection
!= SPECIFIC_VALUE
||
1546 index_value
>= single_value
.n_elements
) set_size(index_value
+ 1);
1547 return single_value
.value_elements
[index_value
];
1550 Base_Template
* Set_Of_Template::get_at(const INTEGER
& index_value
)
1552 if (!index_value
.is_bound())
1553 TTCN_error("Using an unbound integer value for indexing a template of "
1554 "type %s.", get_descriptor()->name
);
1555 return get_at((int)index_value
);
1558 const Base_Template
* Set_Of_Template::get_at(int index_value
) const
1560 if (index_value
< 0)
1561 TTCN_error("Accessing an element of a template for type %s using "
1562 "a negative index: %d.", get_descriptor()->name
, index_value
);
1563 if (template_selection
!= SPECIFIC_VALUE
)
1564 TTCN_error("Accessing an element of a non-specific template for type %s.",
1565 get_descriptor()->name
);
1566 if (index_value
>= single_value
.n_elements
)
1567 TTCN_error("Index overflow in a template of type %s: The index is %d, but "
1568 "the template has only %d elements.", get_descriptor()->name
,
1569 index_value
, single_value
.n_elements
);
1570 return single_value
.value_elements
[index_value
];
1573 const Base_Template
* Set_Of_Template::get_at(const INTEGER
& index_value
) const
1575 if (!index_value
.is_bound())
1576 TTCN_error("Using an unbound integer value for indexing a template of "
1577 "type %s.", get_descriptor()->name
);
1578 return get_at((int)index_value
);
1581 void Set_Of_Template::set_size(int new_size
)
1584 TTCN_error("Internal error: Setting a negative size for a template of "
1585 "type %s.", get_descriptor()->name
);
1586 template_sel old_selection
= template_selection
;
1587 if (old_selection
!= SPECIFIC_VALUE
) {
1589 set_selection(SPECIFIC_VALUE
);
1590 single_value
.n_elements
= 0;
1591 single_value
.value_elements
= NULL
;
1593 if (new_size
> single_value
.n_elements
) {
1594 single_value
.value_elements
= (Base_Template
**)reallocate_pointers((void**)
1595 single_value
.value_elements
, single_value
.n_elements
, new_size
);
1596 if (old_selection
== ANY_VALUE
|| old_selection
== ANY_OR_OMIT
) {
1597 for (int elem_count
= single_value
.n_elements
;
1598 elem_count
< new_size
; elem_count
++) {
1599 single_value
.value_elements
[elem_count
] = create_elem();
1600 single_value
.value_elements
[elem_count
]->set_value(ANY_VALUE
);
1603 for (int elem_count
= single_value
.n_elements
;
1604 elem_count
< new_size
; elem_count
++)
1605 single_value
.value_elements
[elem_count
] = create_elem();
1607 single_value
.n_elements
= new_size
;
1608 } else if (new_size
< single_value
.n_elements
) {
1609 for (int elem_count
= new_size
;
1610 elem_count
< single_value
.n_elements
; elem_count
++)
1611 delete single_value
.value_elements
[elem_count
];
1612 single_value
.value_elements
= (Base_Template
**)reallocate_pointers((void**)
1613 single_value
.value_elements
, single_value
.n_elements
, new_size
);
1614 single_value
.n_elements
= new_size
;
1618 int Set_Of_Template::size_of(boolean is_size
) const
1620 const char* op_name
= is_size
? "size" : "length";
1622 boolean has_any_or_none
= FALSE
;
1624 TTCN_error("Performing %sof() operation on a template of type %s "
1625 "which has an ifpresent attribute.", op_name
, get_descriptor()->name
);
1626 switch (template_selection
)
1628 case SPECIFIC_VALUE
:
1629 case SUPERSET_MATCH
:
1630 case SUBSET_MATCH
: {
1632 has_any_or_none
= FALSE
;
1633 int elem_count
= single_value
.n_elements
;
1635 while (elem_count
>0 && !single_value
.value_elements
[elem_count
-1]->is_bound())
1638 for (int i
=0; i
<elem_count
; i
++)
1640 switch (single_value
.value_elements
[i
]->get_selection())
1643 TTCN_error("Performing %sof() operation on a template of type %s "
1644 "containing omit element.", op_name
, get_descriptor()->name
);
1646 has_any_or_none
= TRUE
;
1653 if (template_selection
==SUPERSET_MATCH
)
1655 has_any_or_none
= TRUE
;
1657 else if (template_selection
==SUBSET_MATCH
)
1659 int max_size
= min_size
;
1661 if (!has_any_or_none
) // [0,max_size]
1663 switch (length_restriction_type
)
1665 case NO_LENGTH_RESTRICTION
:
1666 if (max_size
==0) return 0;
1667 TTCN_error("Performing %sof() operation on a template of type "
1668 "%s with no exact size.", op_name
, get_descriptor()->name
);
1669 case SINGLE_LENGTH_RESTRICTION
:
1670 if (length_restriction
.single_length
<=max_size
)
1671 return length_restriction
.single_length
;
1672 TTCN_error("Performing %sof() operation on an invalid template of "
1673 "type %s. The maximum size (%d) contradicts the length restriction "
1674 "(%d).", op_name
, get_descriptor()->name
, max_size
,
1675 length_restriction
.single_length
);
1676 case RANGE_LENGTH_RESTRICTION
:
1677 if (max_size
==length_restriction
.range_length
.min_length
)
1679 else if (max_size
>length_restriction
.range_length
.min_length
)
1680 TTCN_error("Performing %sof() operation on a template of type %s "
1681 "with no exact size.", op_name
, get_descriptor()->name
);
1683 TTCN_error("Performing %sof() operation on an invalid template of "
1684 "type %s. Maximum size (%d) contradicts the length restriction "
1685 "(%d..%d).", op_name
, get_descriptor()->name
, max_size
,
1686 length_restriction
.range_length
.min_length
,
1687 length_restriction
.range_length
.max_length
);
1689 TTCN_error("Internal error: Template has invalid length restriction type.");
1695 TTCN_error("Performing %sof() operation on a template of type %s"
1696 " containing omit value.", op_name
, get_descriptor()->name
);
1700 has_any_or_none
= TRUE
;
1704 if (value_list
.n_values
<1)
1705 TTCN_error("Performing %sof() operation on a template of type %s "
1706 "containing an empty list.", op_name
, get_descriptor()->name
);
1707 int item_size
= value_list
.list_value
[0]->size_of(is_size
);
1708 for (int i
= 1; i
< value_list
.n_values
; i
++) {
1709 if (value_list
.list_value
[i
]->size_of(is_size
)!=item_size
)
1710 TTCN_error("Performing %sof() operation on a template of type %s "
1711 "containing a value list with different sizes.", op_name
, get_descriptor()->name
);
1713 min_size
= item_size
;
1714 has_any_or_none
= FALSE
;
1717 case COMPLEMENTED_LIST
:
1718 TTCN_error("Performing %sof() operation on a template of type %s "
1719 "containing complemented list.", op_name
, get_descriptor()->name
);
1720 case UNINITIALIZED_TEMPLATE
:
1722 case STRING_PATTERN
:
1724 TTCN_error("Performing %sof() operation on an uninitialized/unsupported "
1725 "template of type %s.", op_name
, get_descriptor()->name
);
1727 return check_section_is_single(min_size
, has_any_or_none
, op_name
,
1728 "a template of type", get_descriptor()->name
);
1731 int Set_Of_Template::n_elem() const
1733 switch (template_selection
) {
1734 case SPECIFIC_VALUE
:
1735 case SUPERSET_MATCH
:
1737 return single_value
.n_elements
;
1739 case COMPLEMENTED_LIST
:
1740 TTCN_error("Performing n_elem() operation on a template of type %s "
1741 "containing complemented list.", get_descriptor()->name
);
1743 case UNINITIALIZED_TEMPLATE
:
1749 case STRING_PATTERN
:
1753 TTCN_error("Performing n_elem() operation on an uninitialized/unsupported "
1754 "template of type %s.", get_descriptor()->name
);
1757 boolean
Set_Of_Template::match_function_specific(
1758 const Base_Type
*value_ptr
, int value_index
,
1759 const Restricted_Length_Template
*template_ptr
, int template_index
,
1762 const Set_Of_Template
* set_tmpl_ptr
= static_cast<const Set_Of_Template
*>(template_ptr
);
1763 if (value_index
>= 0) {
1764 const Record_Of_Type
* recof_ptr
= static_cast<const Record_Of_Type
*>(value_ptr
);
1765 return set_tmpl_ptr
->single_value
.value_elements
[template_index
]->matchv(recof_ptr
->get_at(value_index
), legacy
);
1767 return set_tmpl_ptr
->single_value
.value_elements
[template_index
]->is_any_or_omit();
1771 boolean
Set_Of_Template::match_function_set(
1772 const Base_Type
*value_ptr
, int value_index
,
1773 const Restricted_Length_Template
*template_ptr
, int template_index
,
1776 const Set_Of_Template
* set_tmpl_ptr
= static_cast<const Set_Of_Template
*>(template_ptr
);
1777 if (value_index
>= 0) {
1778 const Record_Of_Type
* recof_ptr
= static_cast<const Record_Of_Type
*>(value_ptr
);
1779 return set_tmpl_ptr
->single_value
.value_elements
[template_index
]->matchv(recof_ptr
->get_at(value_index
), legacy
);
1781 return set_tmpl_ptr
->single_value
.value_elements
[template_index
]->is_any_or_omit();
1785 void Set_Of_Template::log_function(
1786 const Base_Type
*value_ptr
, const Restricted_Length_Template
*template_ptr
,
1787 int index_value
, int index_template
, boolean legacy
)
1789 const Set_Of_Template
* set_tmpl_ptr
= static_cast<const Set_Of_Template
*>(template_ptr
);
1790 const Record_Of_Type
* recof_ptr
= static_cast<const Record_Of_Type
*>(value_ptr
);
1791 if (value_ptr
!= NULL
&& template_ptr
!= NULL
)
1792 set_tmpl_ptr
->single_value
.value_elements
[index_template
]->log_matchv(recof_ptr
->get_at(index_value
), legacy
);
1793 else if (value_ptr
!= NULL
)
1794 recof_ptr
->get_at(index_value
)->log();
1795 else if (template_ptr
!= NULL
)
1796 set_tmpl_ptr
->single_value
.value_elements
[index_template
]->log();
1799 boolean
Set_Of_Template::matchv(const Base_Type
* other_value
,
1800 boolean legacy
) const
1802 const Record_Of_Type
* other_recof
= static_cast<const Record_Of_Type
*>(other_value
);
1803 if (!other_recof
->is_bound())
1804 TTCN_error("Matching an unbound value of type %s with a template.",
1805 other_recof
->get_descriptor()->name
);
1806 int value_length
= other_recof
->size_of();
1807 if (!match_length(value_length
)) return FALSE
;
1808 switch (template_selection
) {
1809 case SPECIFIC_VALUE
:
1810 return match_set_of(other_recof
, value_length
, this,
1811 single_value
.n_elements
, match_function_specific
, legacy
);
1818 case COMPLEMENTED_LIST
:
1819 for (int list_count
= 0; list_count
< value_list
.n_values
; list_count
++)
1820 if (value_list
.list_value
[list_count
]->matchv(other_recof
, legacy
))
1821 return template_selection
== VALUE_LIST
;
1822 return template_selection
== COMPLEMENTED_LIST
;
1823 case SUPERSET_MATCH
:
1825 return match_set_of(other_recof
, value_length
, this,
1826 single_value
.n_elements
, match_function_set
, legacy
);
1828 TTCN_error("Matching with an uninitialized/unsupported template of type %s.",
1829 get_descriptor()->name
);
1834 boolean
Set_Of_Template::is_value() const
1836 if (template_selection
!= SPECIFIC_VALUE
|| is_ifpresent
) return FALSE
;
1837 for (int elem_count
= 0; elem_count
< single_value
.n_elements
; elem_count
++)
1838 if (!single_value
.value_elements
[elem_count
]->is_value()) return FALSE
;
1842 void Set_Of_Template::valueofv(Base_Type
* value
) const
1844 if (template_selection
!= SPECIFIC_VALUE
|| is_ifpresent
)
1845 TTCN_error("Performing a valueof or send operation on a non-specific template of type %s.", get_descriptor()->name
);
1846 Record_Of_Type
* setof_value
= static_cast<Record_Of_Type
*>(value
);
1847 setof_value
->set_size(single_value
.n_elements
);
1848 for (int elem_count
= 0; elem_count
< single_value
.n_elements
; elem_count
++)
1849 single_value
.value_elements
[elem_count
]->valueofv(setof_value
->get_at(elem_count
));
1850 setof_value
->set_err_descr(err_descr
);
1853 void Set_Of_Template::set_value(template_sel other_value
)
1855 check_single_selection(other_value
);
1857 set_selection(other_value
);
1861 void Set_Of_Template::set_type(template_sel template_type
, int list_length
)
1864 switch (template_type
) {
1866 case COMPLEMENTED_LIST
:
1867 value_list
.n_values
= list_length
;
1868 value_list
.list_value
= (Set_Of_Template
**)allocate_pointers(value_list
.n_values
);
1869 for (int list_count
= 0; list_count
< value_list
.n_values
; list_count
++)
1870 value_list
.list_value
[list_count
] = create();
1872 case SUPERSET_MATCH
:
1874 single_value
.n_elements
= list_length
;
1875 single_value
.value_elements
= (Base_Template
**)allocate_pointers(single_value
.n_elements
);
1876 for (int set_count
= 0; set_count
< single_value
.n_elements
; set_count
++)
1877 single_value
.value_elements
[set_count
] = create_elem();
1880 TTCN_error("Internal error: Setting an invalid type for a template of "
1881 "type %s.", get_descriptor()->name
);
1883 set_selection(template_type
);
1886 Set_Of_Template
* Set_Of_Template::get_list_item(int list_index
)
1888 if (template_selection
!= VALUE_LIST
&& template_selection
!= COMPLEMENTED_LIST
)
1889 TTCN_error("Internal error: Accessing a list element of a non-list "
1890 "template of type %s.", get_descriptor()->name
);
1891 if (list_index
>= value_list
.n_values
|| list_index
< 0)
1892 TTCN_error("Internal error: Index overflow in a value list template "
1893 "of type %s.", get_descriptor()->name
);
1894 return value_list
.list_value
[list_index
];
1897 Base_Template
* Set_Of_Template::get_set_item(int set_index
)
1899 if (template_selection
!= SUPERSET_MATCH
&& template_selection
!= SUBSET_MATCH
)
1900 TTCN_error("Internal error: Accessing a set element of a non-set "
1901 "template of type %s.", get_descriptor()->name
);
1902 if (set_index
>= single_value
.n_elements
|| set_index
< 0)
1903 TTCN_error("Internal error: Index overflow in a set template of "
1904 "type %s.", get_descriptor()->name
);
1905 return single_value
.value_elements
[set_index
];
1908 void Set_Of_Template::log() const
1910 switch (template_selection
) {
1911 case SPECIFIC_VALUE
:
1912 if (single_value
.n_elements
> 0) {
1913 TTCN_Logger::log_event_str("{ ");
1914 for (int elem_count
= 0; elem_count
< single_value
.n_elements
; elem_count
++) {
1915 if (elem_count
> 0) TTCN_Logger::log_event_str(", ");
1916 single_value
.value_elements
[elem_count
]->log();
1918 TTCN_Logger::log_event_str(" }");
1919 } else TTCN_Logger::log_event_str("{ }");
1921 case COMPLEMENTED_LIST
:
1922 TTCN_Logger::log_event_str("complement ");
1925 TTCN_Logger::log_char('(');
1926 for (int list_count
= 0; list_count
< value_list
.n_values
; list_count
++) {
1927 if (list_count
> 0) TTCN_Logger::log_event_str(", ");
1928 value_list
.list_value
[list_count
]->log();
1930 TTCN_Logger::log_char(')');
1932 case SUPERSET_MATCH
:
1934 TTCN_Logger::log_event("%s(",
1935 template_selection
== SUPERSET_MATCH
? "superset" : "subset");
1936 for (int set_count
= 0; set_count
< single_value
.n_elements
; set_count
++) {
1937 if (set_count
> 0) TTCN_Logger::log_event_str(", ");
1938 single_value
.value_elements
[set_count
]->log();
1940 TTCN_Logger::log_char(')');
1948 if (err_descr
) err_descr
->log();
1951 void Set_Of_Template::log_matchv(const Base_Type
* match_value
, boolean legacy
) const
1953 if (TTCN_Logger::VERBOSITY_COMPACT
== TTCN_Logger::get_matching_verbosity()) {
1954 if (matchv(match_value
, legacy
)) {
1955 TTCN_Logger::print_logmatch_buffer();
1956 TTCN_Logger::log_event_str(" matched");
1958 size_t previous_size
= TTCN_Logger::get_logmatch_buffer_len();
1959 if (template_selection
== SPECIFIC_VALUE
) {
1960 const Record_Of_Type
* setof_value
= static_cast<const Record_Of_Type
*>(match_value
);
1961 log_match_heuristics(setof_value
, setof_value
->size_of(), this,
1962 single_value
.n_elements
, match_function_specific
, log_function
, legacy
);
1964 if (previous_size
!= 0) {
1965 TTCN_Logger::print_logmatch_buffer();
1966 TTCN_Logger::set_logmatch_buffer_len(previous_size
);
1967 TTCN_Logger::log_event_str(":=");
1970 TTCN_Logger::log_event_str(" with ");
1972 TTCN_Logger::log_event_str(" unmatched");
1977 TTCN_Logger::log_event_str(" with ");
1979 if (matchv(match_value
, legacy
)) TTCN_Logger::log_event_str(" matched");
1981 TTCN_Logger::log_event_str(" unmatched");
1982 if (template_selection
== SPECIFIC_VALUE
) {
1983 const Record_Of_Type
* setof_value
= static_cast<const Record_Of_Type
*>(match_value
);
1984 log_match_heuristics(setof_value
, setof_value
->size_of(), this,
1985 single_value
.n_elements
, match_function_specific
, log_function
, legacy
);
1991 void Set_Of_Template::encode_text(Text_Buf
& text_buf
) const
1993 encode_text_restricted(text_buf
);
1994 switch (template_selection
) {
1995 case SPECIFIC_VALUE
:
1996 case SUPERSET_MATCH
:
1998 text_buf
.push_int(single_value
.n_elements
);
1999 for (int elem_count
= 0; elem_count
< single_value
.n_elements
; elem_count
++)
2000 single_value
.value_elements
[elem_count
]->encode_text(text_buf
);
2007 case COMPLEMENTED_LIST
:
2008 text_buf
.push_int(value_list
.n_values
);
2009 for (int list_count
= 0; list_count
< value_list
.n_values
; list_count
++)
2010 value_list
.list_value
[list_count
]->encode_text(text_buf
);
2013 TTCN_error("Text encoder: Encoding an uninitialized/unsupported template "
2014 "of type %s.", get_descriptor()->name
);
2018 void Set_Of_Template::decode_text(Text_Buf
& text_buf
)
2021 decode_text_restricted(text_buf
);
2022 switch (template_selection
) {
2023 case SPECIFIC_VALUE
:
2024 case SUPERSET_MATCH
:
2026 single_value
.n_elements
= text_buf
.pull_int().get_val();
2027 if (single_value
.n_elements
< 0)
2028 TTCN_error("Text decoder: Negative size was received for a template of "
2029 "type %s.", get_descriptor()->name
);
2030 single_value
.value_elements
= (Base_Template
**)allocate_pointers(single_value
.n_elements
);
2031 for (int elem_count
= 0; elem_count
< single_value
.n_elements
; elem_count
++) {
2032 single_value
.value_elements
[elem_count
] = create_elem();
2033 single_value
.value_elements
[elem_count
]->decode_text(text_buf
);
2041 case COMPLEMENTED_LIST
:
2042 value_list
.n_values
= text_buf
.pull_int().get_val();
2043 value_list
.list_value
= (Set_Of_Template
**)allocate_pointers(value_list
.n_values
);
2044 for (int list_count
= 0; list_count
< value_list
.n_values
; list_count
++) {
2045 value_list
.list_value
[list_count
] = create();
2046 value_list
.list_value
[list_count
]->decode_text(text_buf
);
2050 TTCN_error("Text decoder: An unknown/unsupported selection was received "
2051 "for a template of type %s.", get_descriptor()->name
);
2055 boolean
Set_Of_Template::is_present(boolean legacy
/* = FALSE */) const
2057 if (template_selection
==UNINITIALIZED_TEMPLATE
) return FALSE
;
2058 return !match_omit(legacy
);
2061 boolean
Set_Of_Template::match_omit(boolean legacy
/* = FALSE */) const
2063 if (is_ifpresent
) return TRUE
;
2064 switch (template_selection
) {
2069 case COMPLEMENTED_LIST
:
2071 // legacy behavior: 'omit' can appear in the value/complement list
2072 for (int i
=0; i
<value_list
.n_values
; i
++)
2073 if (value_list
.list_value
[i
]->match_omit())
2074 return template_selection
==VALUE_LIST
;
2075 return template_selection
==COMPLEMENTED_LIST
;
2077 // else fall through
2084 void Set_Of_Template::set_param(Module_Param
& param
)
2086 if (dynamic_cast<Module_Param_Name
*>(param
.get_id()) != NULL
&&
2087 param
.get_id()->next_name()) {
2088 // Haven't reached the end of the module parameter name
2089 // => the name refers to one of the elements, not to the whole record of
2090 char* param_field
= param
.get_id()->get_current_name();
2091 if (param_field
[0] < '0' || param_field
[0] > '9') {
2092 param
.error("Unexpected record field name in module parameter, expected a valid"
2093 " index for set of template type `%s'", get_descriptor()->name
);
2095 int param_index
= -1;
2096 sscanf(param_field
, "%d", ¶m_index
);
2097 get_at(param_index
)->set_param(param
);
2101 param
.basic_check(Module_Param::BC_TEMPLATE
|Module_Param::BC_LIST
, "set of template");
2103 Module_Param_Ptr mp
= ¶m
;
2104 if (param
.get_type() == Module_Param::MP_Reference
) {
2105 mp
= param
.get_referenced_param();
2108 switch (mp
->get_type()) {
2109 case Module_Param::MP_Omit
:
2110 set_value(OMIT_VALUE
);
2112 case Module_Param::MP_Any
:
2113 set_value(ANY_VALUE
);
2115 case Module_Param::MP_AnyOrNone
:
2116 set_value(ANY_OR_OMIT
);
2118 case Module_Param::MP_List_Template
:
2119 case Module_Param::MP_ComplementList_Template
: {
2120 Set_Of_Template
** list_items
= (Set_Of_Template
**)
2121 allocate_pointers(mp
->get_size());
2122 for (size_t i
= 0; i
< mp
->get_size(); i
++) {
2123 list_items
[i
] = create();
2124 list_items
[i
]->set_param(*mp
->get_elem(i
));
2127 template_selection
= mp
->get_type() == Module_Param::MP_List_Template
?
2128 VALUE_LIST
: COMPLEMENTED_LIST
;
2129 value_list
.n_values
= mp
->get_size();
2130 value_list
.list_value
= list_items
;
2132 case Module_Param::MP_Value_List
:
2133 set_size(mp
->get_size());
2134 for (size_t i
=0; i
<mp
->get_size(); ++i
) {
2135 Module_Param
* const curr
= mp
->get_elem(i
);
2136 if (curr
->get_type()!=Module_Param::MP_NotUsed
) {
2137 get_at(i
)->set_param(*curr
);
2141 case Module_Param::MP_Indexed_List
:
2142 if (template_selection
!=SPECIFIC_VALUE
) set_size(0);
2143 for (size_t i
=0; i
<mp
->get_size(); ++i
) {
2144 Module_Param
* const current
= mp
->get_elem(i
);
2145 get_at((int)current
->get_id()->get_index())->set_param(*current
);
2148 case Module_Param::MP_Superset_Template
:
2149 case Module_Param::MP_Subset_Template
:
2150 set_type(mp
->get_type()==Module_Param::MP_Superset_Template
? SUPERSET_MATCH
: SUBSET_MATCH
, mp
->get_size());
2151 for (size_t i
=0; i
<mp
->get_size(); i
++) {
2152 get_set_item((int)i
)->set_param(*mp
->get_elem(i
));
2156 param
.type_error("set of template", get_descriptor()->name
);
2158 is_ifpresent
= param
.get_ifpresent() || mp
->get_ifpresent();
2159 if (param
.get_length_restriction() != NULL
) {
2160 set_length_range(param
);
2163 set_length_range(*mp
);
2167 Module_Param
* Set_Of_Template::get_param(Module_Param_Name
& param_name
) const
2169 if (param_name
.next_name()) {
2170 // Haven't reached the end of the module parameter name
2171 // => the name refers to one of the elements, not to the whole record of
2172 char* param_field
= param_name
.get_current_name();
2173 if (param_field
[0] < '0' || param_field
[0] > '9') {
2174 TTCN_error("Unexpected record field name in module parameter reference, "
2175 "expected a valid index for set of template type `%s'",
2176 get_descriptor()->name
);
2178 int param_index
= -1;
2179 sscanf(param_field
, "%d", ¶m_index
);
2180 return get_at(param_index
)->get_param(param_name
);
2182 Module_Param
* mp
= NULL
;
2183 switch (template_selection
) {
2184 case UNINITIALIZED_TEMPLATE
:
2185 mp
= new Module_Param_Unbound();
2188 mp
= new Module_Param_Omit();
2191 mp
= new Module_Param_Any();
2194 mp
= new Module_Param_AnyOrNone();
2196 case SPECIFIC_VALUE
: {
2197 Vector
<Module_Param
*> values
;
2198 for (int i
= 0; i
< single_value
.n_elements
; ++i
) {
2199 values
.push_back(single_value
.value_elements
[i
]->get_param(param_name
));
2201 mp
= new Module_Param_Value_List();
2202 mp
->add_list_with_implicit_ids(&values
);
2206 case COMPLEMENTED_LIST
: {
2207 if (template_selection
== VALUE_LIST
) {
2208 mp
= new Module_Param_List_Template();
2211 mp
= new Module_Param_ComplementList_Template();
2213 for (int i
= 0; i
< value_list
.n_values
; ++i
) {
2214 mp
->add_elem(value_list
.list_value
[i
]->get_param(param_name
));
2221 mp
->set_ifpresent();
2223 mp
->set_length_restriction(get_length_range());
2227 void Set_Of_Template::check_restriction(template_res t_res
, const char* t_name
,
2228 boolean legacy
/* = FALSE */) const
2230 if (template_selection
==UNINITIALIZED_TEMPLATE
) return;
2231 switch ((t_name
&&(t_res
==TR_VALUE
))?TR_OMIT
:t_res
) {
2233 if (template_selection
==OMIT_VALUE
) return;
2236 if (template_selection
!=SPECIFIC_VALUE
|| is_ifpresent
) break;
2237 for (int i
=0; i
<single_value
.n_elements
; i
++)
2238 single_value
.value_elements
[i
]->check_restriction(t_res
, t_name
? t_name
: get_descriptor()->name
);
2241 if (!match_omit(legacy
)) return;
2246 TTCN_error("Restriction `%s' on template of type %s violated.",
2247 get_res_name(t_res
), t_name
? t_name
: get_descriptor()->name
);
2250 ////////////////////////////////////////////////////////////////////////////////
2252 Record_Template::Record_Template(): Base_Template(), err_descr(NULL
)
2256 Record_Template::Record_Template(template_sel other_value
):
2257 Base_Template(other_value
), err_descr(NULL
)
2259 check_single_selection(other_value
);
2262 Record_Template::~Record_Template()
2267 void Record_Template::clean_up()
2269 switch (template_selection
) {
2270 case SPECIFIC_VALUE
:
2271 for (int elem_count
= 0; elem_count
< single_value
.n_elements
; elem_count
++)
2272 delete single_value
.value_elements
[elem_count
];
2273 free_pointers((void**)single_value
.value_elements
);
2276 case COMPLEMENTED_LIST
:
2277 for (int elem_count
= 0; elem_count
< value_list
.n_values
; elem_count
++)
2278 delete value_list
.list_value
[elem_count
];
2279 free_pointers((void**)value_list
.list_value
);
2284 template_selection
= UNINITIALIZED_TEMPLATE
;
2287 void Record_Template::copy_value(const Base_Type
* other_value
)
2289 if (!other_value
->is_bound())
2290 TTCN_error("Initialization of a record/set template with an unbound value.");
2292 const Record_Type
* other_rec
= static_cast<const Record_Type
*>(other_value
);
2293 const int* optional_indexes
= other_rec
->get_optional_indexes();
2294 int next_optional_idx
= 0;
2295 for (int elem_count
= 0; elem_count
< single_value
.n_elements
; elem_count
++) {
2296 boolean is_optional
= optional_indexes
&& (optional_indexes
[next_optional_idx
]==elem_count
);
2297 if (is_optional
) next_optional_idx
++;
2298 const Base_Type
* elem_value
= other_rec
->get_at(elem_count
);
2299 if (!elem_value
->is_bound()) continue;
2301 if (elem_value
->is_present()) {
2302 single_value
.value_elements
[elem_count
]->copy_value(other_rec
->get_at(elem_count
)->get_opt_value());
2304 single_value
.value_elements
[elem_count
]->set_value(OMIT_VALUE
);
2307 single_value
.value_elements
[elem_count
]->copy_value(other_rec
->get_at(elem_count
));
2310 err_descr
= other_rec
->get_err_descr();
2313 void Record_Template::copy_template(const Record_Template
& other_value
)
2315 switch (other_value
.template_selection
) {
2316 case SPECIFIC_VALUE
:
2317 set_specific(); // FIXME: create_elem(int elem_idx) should be used, but that's more code to generate...
2318 // single_value.n_elements = other_value.single_value.n_elements;
2319 // single_value.value_elements = (Base_Template**)allocate_pointers(single_value.n_elements);
2320 for (int elem_count
= 0; elem_count
< single_value
.n_elements
; elem_count
++) {
2321 if (other_value
.single_value
.value_elements
[elem_count
]->is_bound()) {
2322 delete single_value
.value_elements
[elem_count
]; // FIXME: unbound elements should not be created when the element is bound
2323 single_value
.value_elements
[elem_count
] = other_value
.single_value
.value_elements
[elem_count
]->clone();
2332 case COMPLEMENTED_LIST
:
2333 value_list
.n_values
= other_value
.value_list
.n_values
;
2334 value_list
.list_value
= (Record_Template
**)allocate_pointers(value_list
.n_values
);
2335 for (int list_count
= 0; list_count
< value_list
.n_values
; list_count
++) {
2336 if (other_value
.value_list
.list_value
[list_count
]->is_bound()) {
2337 value_list
.list_value
[list_count
] = static_cast<Record_Template
*>(other_value
.value_list
.list_value
[list_count
]->clone());
2339 value_list
.list_value
[list_count
] = create();
2344 TTCN_error("Copying an uninitialized/unsupported record/set template.");
2347 set_selection(other_value
);
2348 err_descr
= other_value
.err_descr
;
2351 void Record_Template::copy_optional(const Base_Type
* other_value
)
2353 if (other_value
->is_present()) {
2354 const Record_Type
* other_rec
= static_cast<const Record_Type
*>(other_value
->get_opt_value());
2355 copy_value(other_rec
);
2356 } else if (other_value
->is_bound()) {
2357 set_selection(OMIT_VALUE
);
2360 TTCN_error("Initialization of a record/set template with an unbound optional field.");
2364 void Record_Template::set_type(template_sel template_type
, int list_length
)
2366 if (template_type
!= VALUE_LIST
&& template_type
!= COMPLEMENTED_LIST
)
2367 TTCN_error("Setting an invalid list for a template of type %s.", get_descriptor()->name
);
2369 set_selection(template_type
);
2370 value_list
.n_values
= list_length
;
2371 value_list
.list_value
= (Record_Template
**)allocate_pointers(value_list
.n_values
);
2372 for (int list_count
= 0; list_count
< value_list
.n_values
; list_count
++)
2373 value_list
.list_value
[list_count
] = create();
2376 Record_Template
* Record_Template::get_list_item(int list_index
) const
2378 if (template_selection
!= VALUE_LIST
&& template_selection
!= COMPLEMENTED_LIST
)
2379 TTCN_error("Accessing a list element of a non-list template of type %s.", get_descriptor()->name
);
2380 if (list_index
>= value_list
.n_values
|| list_index
< 0)
2381 TTCN_error("Index overflow in a value list template of type %s.", get_descriptor()->name
);
2382 return value_list
.list_value
[list_index
];
2385 int Record_Template::size_of() const
2388 TTCN_error("Performing sizeof() operation on a template of type %s "
2389 "which has an ifpresent attribute.", get_descriptor()->name
);
2390 switch (template_selection
)
2392 case SPECIFIC_VALUE
: {
2394 for (int elem_count
= 0; elem_count
< single_value
.n_elements
; elem_count
++)
2395 if (single_value
.value_elements
[elem_count
]->is_present()) my_size
++;
2399 if (value_list
.n_values
<1)
2400 TTCN_error("Internal error: Performing sizeof() operation on a template of type %s containing an empty list.", get_descriptor()->name
);
2401 int item_size
= value_list
.list_value
[0]->size_of();
2402 for (int i
= 1; i
< value_list
.n_values
; i
++)
2403 if (value_list
.list_value
[i
]->size_of()!=item_size
)
2404 TTCN_error("Performing sizeof() operation on a template of type %s containing a value list with different sizes.", get_descriptor()->name
);
2408 TTCN_error("Performing sizeof() operation on a template of type %s containing omit value.", get_descriptor()->name
);
2411 TTCN_error("Performing sizeof() operation on a template of type %s containing */? value.", get_descriptor()->name
);
2412 case COMPLEMENTED_LIST
:
2413 TTCN_error("Performing sizeof() operation on a template of type %s containing complemented list.", get_descriptor()->name
);
2415 TTCN_error("Performing sizeof() operation on an uninitialized/unsupported template of type %s.", get_descriptor()->name
);
2420 boolean
Record_Template::is_value() const
2422 if (template_selection
!= SPECIFIC_VALUE
|| is_ifpresent
) return FALSE
;
2423 for (int elem_count
= 0; elem_count
< single_value
.n_elements
; elem_count
++) {
2424 const Base_Template
* tmpl_elem
= single_value
.value_elements
[elem_count
];
2425 if (tmpl_elem
->get_selection()!=OMIT_VALUE
&& !tmpl_elem
->is_value()) return FALSE
;
2430 void Record_Template::valueofv(Base_Type
* value
) const
2432 if (template_selection
!= SPECIFIC_VALUE
|| is_ifpresent
)
2433 TTCN_error("Performing a valueof or send operation on a non-specific template of type %s.", get_descriptor()->name
);
2434 Record_Type
* rec_value
= static_cast<Record_Type
*>(value
);
2435 const int* optional_indexes
= rec_value
->get_optional_indexes();
2436 int next_optional_idx
= 0;
2437 for (int elem_count
= 0; elem_count
< single_value
.n_elements
; elem_count
++) {
2438 boolean is_optional
= optional_indexes
&& (optional_indexes
[next_optional_idx
]==elem_count
);
2440 if (single_value
.value_elements
[elem_count
]->get_selection()==OMIT_VALUE
) {
2441 rec_value
->get_at(elem_count
)->set_to_omit();
2443 rec_value
->get_at(elem_count
)->set_to_present(); // create instance of optional value object
2444 single_value
.value_elements
[elem_count
]->valueofv(rec_value
->get_at(elem_count
)->get_opt_value());
2447 single_value
.value_elements
[elem_count
]->valueofv(rec_value
->get_at(elem_count
));
2449 if (is_optional
) next_optional_idx
++;
2451 rec_value
->set_err_descr(err_descr
);
2454 void Record_Template::set_value(template_sel other_value
)
2456 check_single_selection(other_value
);
2458 set_selection(other_value
);
2462 Base_Template
* Record_Template::get_at(int index_value
)
2465 if (index_value
< 0 || index_value
>= single_value
.n_elements
)
2466 TTCN_error("Internal error: accessing an element of a template of type %s using an "
2467 "invalid index: %d.", get_descriptor()->name
, index_value
);
2468 return single_value
.value_elements
[index_value
];
2471 const Base_Template
* Record_Template::get_at(int index_value
) const
2473 if (index_value
< 0 || index_value
>= single_value
.n_elements
)
2474 TTCN_error("Internal error: accessing an element of a template of type %s using an "
2475 "invalid index: %d.", get_descriptor()->name
, index_value
);
2476 if (template_selection
!= SPECIFIC_VALUE
)
2477 TTCN_error("Accessing field %s of a non-specific template of type %s.",
2478 fld_name(index_value
), get_descriptor()->name
);
2479 return single_value
.value_elements
[index_value
];
2482 Base_Template
* Record_Template::clone() const
2484 Record_Template
* rec
= create();
2485 rec
->copy_template(*this);
2489 void Record_Template::log() const
2491 switch (template_selection
) {
2492 case SPECIFIC_VALUE
:
2493 if (single_value
.n_elements
> 0) {
2494 TTCN_Logger::log_event_str("{ ");
2495 for (int elem_count
= 0; elem_count
< single_value
.n_elements
; elem_count
++) {
2496 if (elem_count
> 0) TTCN_Logger::log_event_str(", ");
2497 TTCN_Logger::log_event_str(fld_name(elem_count
));
2498 TTCN_Logger::log_event_str(" := ");
2499 single_value
.value_elements
[elem_count
]->log();
2501 TTCN_Logger::log_event_str(" }");
2502 } else TTCN_Logger::log_event_str("{ }");
2504 case COMPLEMENTED_LIST
:
2505 TTCN_Logger::log_event_str("complement ");
2508 TTCN_Logger::log_char('(');
2509 for (int list_count
= 0; list_count
< value_list
.n_values
; list_count
++) {
2510 if (list_count
> 0) TTCN_Logger::log_event_str(", ");
2511 value_list
.list_value
[list_count
]->log();
2513 TTCN_Logger::log_char(')');
2520 if (err_descr
) err_descr
->log();
2523 boolean
Record_Template::matchv(const Base_Type
* other_value
,
2524 boolean legacy
) const
2526 switch (template_selection
) {
2532 case SPECIFIC_VALUE
: {
2533 const Record_Type
* other_rec
= static_cast<const Record_Type
*>(other_value
);
2534 const int* optional_indexes
= other_rec
->get_optional_indexes();
2535 int next_optional_idx
= 0;
2536 for (int elem_count
= 0; elem_count
< single_value
.n_elements
; elem_count
++) {
2537 boolean is_optional
= optional_indexes
&& (optional_indexes
[next_optional_idx
]==elem_count
);
2538 const Base_Template
* elem_tmpl
= single_value
.value_elements
[elem_count
];
2539 const Base_Type
* elem_value
= other_rec
->get_at(elem_count
);
2540 if (!elem_value
->is_bound()) return FALSE
;
2541 boolean elem_match
= is_optional
?
2542 ( elem_value
->ispresent() ? elem_tmpl
->matchv(elem_value
->get_opt_value(), legacy
) : elem_tmpl
->match_omit(legacy
) ) :
2543 elem_tmpl
->matchv(other_rec
->get_at(elem_count
), legacy
);
2544 if (!elem_match
) return FALSE
;
2545 if (is_optional
) next_optional_idx
++;
2549 case COMPLEMENTED_LIST
:
2550 for (int list_count
= 0; list_count
< value_list
.n_values
; list_count
++)
2551 if (value_list
.list_value
[list_count
]->matchv(other_value
, legacy
)) return template_selection
== VALUE_LIST
;
2552 return template_selection
== COMPLEMENTED_LIST
;
2554 TTCN_error("Matching an uninitialized/unsupported template of type %s.", get_descriptor()->name
);
2559 void Record_Template::log_matchv(const Base_Type
* match_value
, boolean legacy
) const
2561 if (TTCN_Logger::VERBOSITY_COMPACT
== TTCN_Logger::get_matching_verbosity()) {
2562 if (matchv(match_value
, legacy
)) {
2563 TTCN_Logger::print_logmatch_buffer();
2564 TTCN_Logger::log_event_str(" matched");
2566 if (template_selection
== SPECIFIC_VALUE
) {
2567 size_t previous_size
= TTCN_Logger::get_logmatch_buffer_len();
2568 const Record_Type
* match_rec
= static_cast<const Record_Type
*>(match_value
);
2569 const int* optional_indexes
= match_rec
->get_optional_indexes();
2570 int next_optional_idx
= 0;
2571 for (int elem_count
= 0; elem_count
< single_value
.n_elements
; elem_count
++) {
2572 boolean is_optional
= optional_indexes
&& (optional_indexes
[next_optional_idx
]==elem_count
);
2573 const Base_Template
* elem_tmpl
= single_value
.value_elements
[elem_count
];
2574 const Base_Type
* elem_value
= match_rec
->get_at(elem_count
);
2576 if (elem_value
->ispresent()) {
2577 if (!elem_tmpl
->matchv(elem_value
->get_opt_value(), legacy
)) {
2578 TTCN_Logger::log_logmatch_info(".%s", fld_name(elem_count
));
2579 elem_tmpl
->log_matchv(elem_value
->get_opt_value(), legacy
);
2580 TTCN_Logger::set_logmatch_buffer_len(previous_size
);
2583 if (!elem_tmpl
->match_omit(legacy
)) {
2584 TTCN_Logger::log_logmatch_info(".%s := omit with ", fld_name(elem_count
));
2585 TTCN_Logger::print_logmatch_buffer();
2587 TTCN_Logger::log_event_str(" unmatched");
2588 TTCN_Logger::set_logmatch_buffer_len(previous_size
);
2592 if (!elem_tmpl
->matchv(elem_value
, legacy
)) {
2593 TTCN_Logger::log_logmatch_info(".%s", fld_name(elem_count
));
2594 elem_tmpl
->log_matchv(elem_value
, legacy
);
2595 TTCN_Logger::set_logmatch_buffer_len(previous_size
);
2598 if (is_optional
) next_optional_idx
++;
2601 TTCN_Logger::print_logmatch_buffer();
2603 TTCN_Logger::log_event_str(" with ");
2605 TTCN_Logger::log_event_str(" unmatched");
2609 if (template_selection
== SPECIFIC_VALUE
) {
2610 const Record_Type
* match_rec
= static_cast<const Record_Type
*>(match_value
);
2611 const int* optional_indexes
= match_rec
->get_optional_indexes();
2612 int next_optional_idx
= 0;
2613 TTCN_Logger::log_event_str("{ ");
2614 for (int elem_count
= 0; elem_count
< single_value
.n_elements
; elem_count
++) {
2615 boolean is_optional
= optional_indexes
&& (optional_indexes
[next_optional_idx
]==elem_count
);
2616 const Base_Template
* elem_tmpl
= single_value
.value_elements
[elem_count
];
2617 const Base_Type
* elem_value
= match_rec
->get_at(elem_count
);
2618 if (elem_count
) TTCN_Logger::log_event_str(", ");
2619 TTCN_Logger::log_event_str(fld_name(elem_count
));
2620 TTCN_Logger::log_event_str(" := ");
2622 if (elem_value
->ispresent()) elem_tmpl
->log_matchv(elem_value
->get_opt_value(), legacy
);
2624 TTCN_Logger::log_event_str("omit with ");
2626 if (elem_tmpl
->match_omit(legacy
)) TTCN_Logger::log_event_str(" matched");
2627 else TTCN_Logger::log_event_str(" unmatched");
2630 elem_tmpl
->log_matchv(elem_value
, legacy
);
2632 if (is_optional
) next_optional_idx
++;
2634 TTCN_Logger::log_event_str(" }");
2637 TTCN_Logger::log_event_str(" with ");
2639 if (matchv(match_value
, legacy
)) TTCN_Logger::log_event_str(" matched");
2640 else TTCN_Logger::log_event_str(" unmatched");
2645 void Record_Template::encode_text(Text_Buf
& text_buf
) const
2647 encode_text_base(text_buf
);
2648 switch (template_selection
) {
2649 case SPECIFIC_VALUE
:
2650 for (int elem_count
= 0; elem_count
< single_value
.n_elements
; elem_count
++)
2651 single_value
.value_elements
[elem_count
]->encode_text(text_buf
);
2658 case COMPLEMENTED_LIST
:
2659 text_buf
.push_int(value_list
.n_values
);
2660 for (int list_count
= 0; list_count
< value_list
.n_values
; list_count
++)
2661 value_list
.list_value
[list_count
]->encode_text(text_buf
);
2664 TTCN_error("Text encoder: Encoding an uninitialized/unsupported template"
2665 " of type %s.", get_descriptor()->name
);
2669 void Record_Template::decode_text(Text_Buf
& text_buf
)
2672 decode_text_base(text_buf
);
2673 switch (template_selection
) {
2674 case SPECIFIC_VALUE
:
2675 template_selection
= UNINITIALIZED_TEMPLATE
; //set_specific will set it
2677 for (int elem_count
= 0; elem_count
< single_value
.n_elements
; elem_count
++)
2678 single_value
.value_elements
[elem_count
]->decode_text(text_buf
);
2685 case COMPLEMENTED_LIST
:
2686 value_list
.n_values
= text_buf
.pull_int().get_val();
2687 value_list
.list_value
= (Record_Template
**)allocate_pointers(value_list
.n_values
);
2688 for (int list_count
= 0; list_count
< value_list
.n_values
; list_count
++) {
2689 value_list
.list_value
[list_count
] = create();
2690 value_list
.list_value
[list_count
]->decode_text(text_buf
);
2694 TTCN_error("Text decoder: An unknown/unsupported selection was received in a template of type %s.", get_descriptor()->name
);
2698 boolean
Record_Template::is_present(boolean legacy
/*= FALSE*/) const
2700 if (template_selection
==UNINITIALIZED_TEMPLATE
) return FALSE
;
2701 return !match_omit(legacy
);
2704 boolean
Record_Template::match_omit(boolean legacy
/*= FALSE*/) const
2706 if (is_ifpresent
) return TRUE
;
2707 switch (template_selection
) {
2712 case COMPLEMENTED_LIST
:
2714 // legacy behavior: 'omit' can appear in the value/complement list
2715 for (int i
=0; i
<value_list
.n_values
; i
++)
2716 if (value_list
.list_value
[i
]->match_omit()) return template_selection
==VALUE_LIST
;
2717 return template_selection
==COMPLEMENTED_LIST
;
2719 // else fall through
2726 void Record_Template::set_param(Module_Param
& param
)
2728 if (dynamic_cast<Module_Param_Name
*>(param
.get_id()) != NULL
&&
2729 param
.get_id()->next_name()) {
2730 // Haven't reached the end of the module parameter name
2731 // => the name refers to one of the fields, not to the whole record
2732 char* param_field
= param
.get_id()->get_current_name();
2733 if (param_field
[0] >= '0' && param_field
[0] <= '9') {
2734 param
.error("Unexpected array index in module parameter, expected a valid field"
2735 " name for record/set template type `%s'", get_descriptor()->name
);
2738 for (int field_idx
= 0; field_idx
< single_value
.n_elements
; field_idx
++) {
2739 if (strcmp(fld_name(field_idx
), param_field
) == 0) {
2740 single_value
.value_elements
[field_idx
]->set_param(param
);
2744 param
.error("Field `%s' not found in record/set template type `%s'",
2745 param_field
, get_descriptor()->name
);
2748 param
.basic_check(Module_Param::BC_TEMPLATE
, "record/set template");
2750 Module_Param_Ptr mp
= ¶m
;
2751 if (param
.get_type() == Module_Param::MP_Reference
) {
2752 mp
= param
.get_referenced_param();
2755 switch (mp
->get_type()) {
2756 case Module_Param::MP_Omit
:
2757 set_value(OMIT_VALUE
);
2759 case Module_Param::MP_Any
:
2760 set_value(ANY_VALUE
);
2762 case Module_Param::MP_AnyOrNone
:
2763 set_value(ANY_OR_OMIT
);
2765 case Module_Param::MP_List_Template
:
2766 case Module_Param::MP_ComplementList_Template
: {
2767 Record_Template
** list_items
= (Record_Template
**)
2768 allocate_pointers(mp
->get_size());
2769 for (size_t i
= 0; i
< mp
->get_size(); i
++) {
2770 list_items
[i
] = create();
2771 list_items
[i
]->set_param(*mp
->get_elem(i
));
2774 template_selection
= mp
->get_type() == Module_Param::MP_List_Template
?
2775 VALUE_LIST
: COMPLEMENTED_LIST
;
2776 value_list
.n_values
= mp
->get_size();
2777 value_list
.list_value
= list_items
;
2779 case Module_Param::MP_Value_List
:
2781 if (single_value
.n_elements
<(int)mp
->get_size()) {
2782 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());
2784 for (size_t i
=0; i
<mp
->get_size(); i
++) {
2785 Module_Param
* mp_field
= mp
->get_elem(i
);
2786 if (mp_field
->get_type()!=Module_Param::MP_NotUsed
) {
2787 get_at((int)i
)->set_param(*mp_field
);
2791 case Module_Param::MP_Assignment_List
:
2793 for (size_t i
=0; i
<mp
->get_size(); ++i
) {
2794 Module_Param
* const current
= mp
->get_elem(i
);
2796 for (int j
=0; j
<single_value
.n_elements
; ++j
) {
2797 if (!strcmp(fld_name(j
), current
->get_id()->get_name())) {
2798 if (current
->get_type()!=Module_Param::MP_NotUsed
) {
2799 get_at(j
)->set_param(*current
);
2806 current
->error("Non existent field name in type %s: %s.", get_descriptor()->name
, current
->get_id()->get_name());
2811 param
.type_error("record/set template", get_descriptor()->name
);
2813 is_ifpresent
= param
.get_ifpresent() || mp
->get_ifpresent();
2816 Module_Param
* Record_Template::get_param(Module_Param_Name
& param_name
) const
2818 if (param_name
.next_name()) {
2819 // Haven't reached the end of the module parameter name
2820 // => the name refers to one of the fields, not to the whole record
2821 char* param_field
= param_name
.get_current_name();
2822 if (param_field
[0] >= '0' && param_field
[0] <= '9') {
2823 TTCN_error("Unexpected array index in module parameter reference, "
2824 "expected a valid field name for record/set template type `%s'",
2825 get_descriptor()->name
);
2827 for (int field_idx
= 0; field_idx
< single_value
.n_elements
; field_idx
++) {
2828 if (strcmp(fld_name(field_idx
), param_field
) == 0) {
2829 return get_at(field_idx
)->get_param(param_name
);
2832 TTCN_error("Field `%s' not found in record/set type `%s'",
2833 param_field
, get_descriptor()->name
);
2835 Module_Param
* mp
= NULL
;
2836 switch (template_selection
) {
2837 case UNINITIALIZED_TEMPLATE
:
2838 mp
= new Module_Param_Unbound();
2841 mp
= new Module_Param_Omit();
2844 mp
= new Module_Param_Any();
2847 mp
= new Module_Param_AnyOrNone();
2849 case SPECIFIC_VALUE
: {
2850 mp
= new Module_Param_Assignment_List();
2851 for (int i
= 0; i
< single_value
.n_elements
; ++i
) {
2852 Module_Param
* mp_field
= get_at(i
)->get_param(param_name
);
2853 mp_field
->set_id(new Module_Param_FieldName(mcopystr(fld_name(i
))));
2854 mp
->add_elem(mp_field
);
2858 case COMPLEMENTED_LIST
: {
2859 if (template_selection
== VALUE_LIST
) {
2860 mp
= new Module_Param_List_Template();
2863 mp
= new Module_Param_ComplementList_Template();
2865 for (int i
= 0; i
< value_list
.n_values
; ++i
) {
2866 mp
->add_elem(value_list
.list_value
[i
]->get_param(param_name
));
2873 mp
->set_ifpresent();
2878 void Record_Template::check_restriction(template_res t_res
, const char* t_name
,
2879 boolean legacy
/* = FALSE */) const
2881 if (template_selection
==UNINITIALIZED_TEMPLATE
) return;
2882 switch ((t_name
&&(t_res
==TR_VALUE
))?TR_OMIT
:t_res
) {
2884 if (template_selection
==OMIT_VALUE
) return;
2887 if (template_selection
!=SPECIFIC_VALUE
|| is_ifpresent
) break;
2888 for (int i
=0; i
<single_value
.n_elements
; i
++)
2889 single_value
.value_elements
[i
]->check_restriction(t_res
, t_name
? t_name
: get_descriptor()->name
);
2892 if (!match_omit(legacy
)) return;
2897 TTCN_error("Restriction `%s' on template of type %s violated.",
2898 get_res_name(t_res
), t_name
? t_name
: get_descriptor()->name
);
2901 ////////////////////////////////////////////////////////////////////////////////
2903 Empty_Record_Template::Empty_Record_Template(): Base_Template()
2907 Empty_Record_Template::Empty_Record_Template(template_sel other_value
):
2908 Base_Template(other_value
)
2910 check_single_selection(other_value
);
2913 Empty_Record_Template::~Empty_Record_Template()
2918 void Empty_Record_Template::clean_up()
2920 switch (template_selection
) {
2922 case COMPLEMENTED_LIST
:
2923 for (int elem_count
= 0; elem_count
< value_list
.n_values
; elem_count
++)
2924 delete value_list
.list_value
[elem_count
];
2925 free_pointers((void**)value_list
.list_value
);
2930 template_selection
= UNINITIALIZED_TEMPLATE
;
2933 void Empty_Record_Template::copy_value(const Base_Type
* other_value
)
2935 if (!other_value
->is_bound())
2936 TTCN_error("Initialization of a record/set template with an unbound value.");
2937 set_selection(SPECIFIC_VALUE
);
2940 void Empty_Record_Template::copy_template(const Empty_Record_Template
& other_value
)
2942 switch (other_value
.template_selection
) {
2943 case SPECIFIC_VALUE
:
2949 case COMPLEMENTED_LIST
:
2950 value_list
.n_values
= other_value
.value_list
.n_values
;
2951 value_list
.list_value
= (Empty_Record_Template
**)allocate_pointers(value_list
.n_values
);
2952 for (int list_count
= 0; list_count
< value_list
.n_values
; list_count
++)
2953 value_list
.list_value
[list_count
] = static_cast<Empty_Record_Template
*>(other_value
.value_list
.list_value
[list_count
]->clone());
2956 TTCN_error("Copying an uninitialized/unsupported record/set template.");
2959 set_selection(other_value
);
2962 void Empty_Record_Template::copy_optional(const Base_Type
* other_value
)
2964 if (other_value
->is_present()) {
2965 const Empty_Record_Type
* other_rec
= static_cast<const Empty_Record_Type
*>(other_value
->get_opt_value());
2966 copy_value(other_rec
);
2967 } else if (other_value
->is_bound()) {
2968 set_selection(OMIT_VALUE
);
2970 TTCN_error("Initialization of a record/set template with an unbound optional field.");
2974 void Empty_Record_Template::set_type(template_sel template_type
, int list_length
)
2976 if (template_type
!= VALUE_LIST
&& template_type
!= COMPLEMENTED_LIST
)
2977 TTCN_error("Setting an invalid list for a template of type %s.", get_descriptor()->name
);
2979 set_selection(template_type
);
2980 value_list
.n_values
= list_length
;
2981 value_list
.list_value
= (Empty_Record_Template
**)allocate_pointers(value_list
.n_values
);
2982 for (int list_count
= 0; list_count
< value_list
.n_values
; list_count
++)
2983 value_list
.list_value
[list_count
] = create();
2986 Empty_Record_Template
* Empty_Record_Template::get_list_item(int list_index
) const
2988 if (template_selection
!= VALUE_LIST
&& template_selection
!= COMPLEMENTED_LIST
)
2989 TTCN_error("Accessing a list element of a non-list template of type %s.", get_descriptor()->name
);
2990 if (list_index
>= value_list
.n_values
|| list_index
< 0)
2991 TTCN_error("Index overflow in a value list template of type %s.", get_descriptor()->name
);
2992 return value_list
.list_value
[list_index
];
2995 int Empty_Record_Template::size_of() const
2998 TTCN_error("Performing sizeof() operation on a template of type %s "
2999 "which has an ifpresent attribute.", get_descriptor()->name
);
3000 switch (template_selection
)
3002 case SPECIFIC_VALUE
:
3005 if (value_list
.n_values
<1)
3006 TTCN_error("Internal error: Performing sizeof() operation on a template of type %s containing an empty list.", get_descriptor()->name
);
3007 int item_size
= value_list
.list_value
[0]->size_of();
3008 for (int i
= 1; i
< value_list
.n_values
; i
++)
3009 if (value_list
.list_value
[i
]->size_of()!=item_size
)
3010 TTCN_error("Performing sizeof() operation on a template of type %s containing a value list with different sizes.", get_descriptor()->name
);
3014 TTCN_error("Performing sizeof() operation on a template of type %s containing omit value.", get_descriptor()->name
);
3017 TTCN_error("Performing sizeof() operation on a template of type %s containing */? value.", get_descriptor()->name
);
3018 case COMPLEMENTED_LIST
:
3019 TTCN_error("Performing sizeof() operation on a template of type %s containing complemented list.", get_descriptor()->name
);
3021 TTCN_error("Performing sizeof() operation on an uninitialized/unsupported template of type %s.", get_descriptor()->name
);
3026 boolean
Empty_Record_Template::is_value() const
3028 return (template_selection
== SPECIFIC_VALUE
&& !is_ifpresent
);
3031 void Empty_Record_Template::valueofv(Base_Type
* value
) const
3033 if (template_selection
!= SPECIFIC_VALUE
|| is_ifpresent
)
3034 TTCN_error("Performing a valueof or send operation on a non-specific template of type %s.", get_descriptor()->name
);
3035 Empty_Record_Type
* rec_value
= static_cast<Empty_Record_Type
*>(value
);
3036 rec_value
->set_null();
3039 void Empty_Record_Template::set_value(template_sel other_value
)
3041 check_single_selection(other_value
);
3043 set_selection(other_value
);
3046 Base_Template
* Empty_Record_Template::clone() const
3048 Empty_Record_Template
* rec
= create();
3049 rec
->copy_template(*this);
3053 void Empty_Record_Template::log() const
3055 switch (template_selection
) {
3056 case SPECIFIC_VALUE
:
3057 TTCN_Logger::log_event_str("{ }");
3059 case COMPLEMENTED_LIST
:
3060 TTCN_Logger::log_event_str("complement ");
3063 TTCN_Logger::log_char('(');
3064 for (int list_count
= 0; list_count
< value_list
.n_values
; list_count
++) {
3065 if (list_count
> 0) TTCN_Logger::log_event_str(", ");
3066 value_list
.list_value
[list_count
]->log();
3068 TTCN_Logger::log_char(')');
3077 boolean
Empty_Record_Template::matchv(const Base_Type
* other_value
,
3078 boolean legacy
) const
3080 switch (template_selection
) {
3086 case SPECIFIC_VALUE
:
3089 case COMPLEMENTED_LIST
:
3090 for (int list_count
= 0; list_count
< value_list
.n_values
; list_count
++)
3091 if (value_list
.list_value
[list_count
]->matchv(other_value
, legacy
)) return template_selection
== VALUE_LIST
;
3092 return template_selection
== COMPLEMENTED_LIST
;
3094 TTCN_error("Matching an uninitialized/unsupported template of type %s.", get_descriptor()->name
);
3099 void Empty_Record_Template::log_matchv(const Base_Type
* match_value
, boolean legacy
) const
3102 TTCN_Logger::log_event_str(" with ");
3104 if (matchv(match_value
, legacy
)) TTCN_Logger::log_event_str(" matched");
3105 else TTCN_Logger::log_event_str(" unmatched");
3108 void Empty_Record_Template::encode_text(Text_Buf
& text_buf
) const
3110 encode_text_base(text_buf
);
3111 switch (template_selection
) {
3112 case SPECIFIC_VALUE
:
3118 case COMPLEMENTED_LIST
:
3119 text_buf
.push_int(value_list
.n_values
);
3120 for (int list_count
= 0; list_count
< value_list
.n_values
; list_count
++)
3121 value_list
.list_value
[list_count
]->encode_text(text_buf
);
3124 TTCN_error("Text encoder: Encoding an uninitialized/unsupported template of type %s.", get_descriptor()->name
);
3128 void Empty_Record_Template::decode_text(Text_Buf
& text_buf
)
3131 decode_text_base(text_buf
);
3132 switch (template_selection
) {
3133 case SPECIFIC_VALUE
:
3139 case COMPLEMENTED_LIST
:
3140 value_list
.n_values
= text_buf
.pull_int().get_val();
3141 value_list
.list_value
= (Empty_Record_Template
**)allocate_pointers(value_list
.n_values
);
3142 for (int list_count
= 0; list_count
< value_list
.n_values
; list_count
++) {
3143 value_list
.list_value
[list_count
] = create();
3144 value_list
.list_value
[list_count
]->decode_text(text_buf
);
3148 TTCN_error("Text decoder: An unknown/unsupported selection was received in a template of type %s.", get_descriptor()->name
);
3152 boolean
Empty_Record_Template::is_present(boolean legacy
/*= FALSE*/) const
3154 if (template_selection
==UNINITIALIZED_TEMPLATE
) return FALSE
;
3155 return !match_omit(legacy
);
3158 boolean
Empty_Record_Template::match_omit(boolean legacy
/* = FALSE */) const
3160 if (is_ifpresent
) return TRUE
;
3161 switch (template_selection
) {
3166 case COMPLEMENTED_LIST
:
3168 // legacy behavior: 'omit' can appear in the value/complement list
3169 for (int i
=0; i
<value_list
.n_values
; i
++)
3170 if (value_list
.list_value
[i
]->match_omit()) return template_selection
==VALUE_LIST
;
3171 return template_selection
==COMPLEMENTED_LIST
;
3173 // else fall through
3180 void Empty_Record_Template::set_param(Module_Param
& param
)
3182 param
.basic_check(Module_Param::BC_TEMPLATE
, "empty record/set template");
3183 Module_Param_Ptr mp
= ¶m
;
3184 if (param
.get_type() == Module_Param::MP_Reference
) {
3185 mp
= param
.get_referenced_param();
3187 switch (mp
->get_type()) {
3188 case Module_Param::MP_Omit
:
3189 set_value(OMIT_VALUE
);
3191 case Module_Param::MP_Any
:
3192 set_value(ANY_VALUE
);
3194 case Module_Param::MP_AnyOrNone
:
3195 set_value(ANY_OR_OMIT
);
3197 case Module_Param::MP_List_Template
:
3198 case Module_Param::MP_ComplementList_Template
: {
3199 Empty_Record_Template
** list_items
= (Empty_Record_Template
**)
3200 allocate_pointers(mp
->get_size());
3201 for (size_t i
= 0; i
< mp
->get_size(); i
++) {
3202 list_items
[i
] = create();
3203 list_items
[i
]->set_param(*mp
->get_elem(i
));
3206 template_selection
= mp
->get_type() == Module_Param::MP_List_Template
?
3207 VALUE_LIST
: COMPLEMENTED_LIST
;
3208 value_list
.n_values
= mp
->get_size();
3209 value_list
.list_value
= list_items
;
3211 case Module_Param::MP_Value_List
:
3212 if (mp
->get_size()==0) {
3213 set_selection(SPECIFIC_VALUE
);
3215 else param
.type_error("empty record/set template", get_descriptor()->name
);
3218 param
.type_error("empty record/set template", get_descriptor()->name
);
3220 is_ifpresent
= param
.get_ifpresent() || mp
->get_ifpresent();
3223 Module_Param
* Empty_Record_Template::get_param(Module_Param_Name
& param_name
) const
3225 Module_Param
* mp
= NULL
;
3226 switch (template_selection
) {
3227 case UNINITIALIZED_TEMPLATE
:
3228 mp
= new Module_Param_Unbound();
3231 mp
= new Module_Param_Omit();
3234 mp
= new Module_Param_Any();
3237 mp
= new Module_Param_AnyOrNone();
3239 case SPECIFIC_VALUE
:
3240 mp
= new Module_Param_Value_List();
3243 case COMPLEMENTED_LIST
: {
3244 if (template_selection
== VALUE_LIST
) {
3245 mp
= new Module_Param_List_Template();
3248 mp
= new Module_Param_ComplementList_Template();
3250 for (int i
= 0; i
< value_list
.n_values
; ++i
) {
3251 mp
->add_elem(value_list
.list_value
[i
]->get_param(param_name
));
3258 mp
->set_ifpresent();