Sync with 5.4.0
[deliverable/titan.core.git] / core / Template.cc
CommitLineData
970ed795 1///////////////////////////////////////////////////////////////////////////////
3abe9331 2// Copyright (c) 2000-2015 Ericsson Telecom AB
970ed795
EL
3// All rights reserved. This program and the accompanying materials
4// are made available under the terms of the Eclipse Public License v1.0
5// which accompanies this distribution, and is available at
6// http://www.eclipse.org/legal/epl-v10.html
7///////////////////////////////////////////////////////////////////////////////
8#include <string.h>
9
10#include "../common/memory.h"
11#include "Template.hh"
12#include "Error.hh"
13#include "Logger.hh"
14#include "Textbuf.hh"
15#include "Param_Types.hh"
16
17#ifdef TITAN_RUNTIME_2
18#include "Integer.hh"
19
3abe9331 20void Base_Template::check_restriction(template_res t_res, const char* t_name,
21 boolean legacy /* = FALSE */) const
970ed795
EL
22{
23 if (template_selection==UNINITIALIZED_TEMPLATE) return;
24 switch ((t_name&&(t_res==TR_VALUE))?TR_OMIT:t_res) {
25 case TR_VALUE:
26 if (!is_ifpresent && template_selection==SPECIFIC_VALUE) return;
27 break;
28 case TR_OMIT:
29 if (!is_ifpresent && (template_selection==OMIT_VALUE ||
30 template_selection==SPECIFIC_VALUE)) return;
31 break;
32 case TR_PRESENT:
3abe9331 33 if (!match_omit(legacy)) return;
970ed795
EL
34 break;
35 default:
36 return;
37 }
38 TTCN_error("Restriction `%s' on template of type %s violated.",
39 get_res_name(t_res), t_name ? t_name : get_descriptor()->name);
40}
41#endif
42
43Base_Template::Base_Template()
44: template_selection(UNINITIALIZED_TEMPLATE), is_ifpresent(FALSE)
45{}
46
47Base_Template::Base_Template(template_sel other_value)
48: template_selection(other_value), is_ifpresent(FALSE)
49{}
50
51void Base_Template::check_single_selection(template_sel other_value)
52{
53 switch (other_value) {
54 case ANY_VALUE:
55 case OMIT_VALUE:
56 case ANY_OR_OMIT:
57 break;
58 default:
59 TTCN_error("Initialization of a template with an invalid selection.");
60 }
61}
62
63void Base_Template::set_selection(template_sel other_value)
64{
65 template_selection = other_value;
66 is_ifpresent = FALSE;
67}
68
69void Base_Template::set_selection(const Base_Template& other_value)
70{
71 template_selection = other_value.template_selection;
72 is_ifpresent = other_value.is_ifpresent;
73}
74
75void Base_Template::log_generic() const
76{
77 switch (template_selection) {
78 case UNINITIALIZED_TEMPLATE:
79 TTCN_Logger::log_event_uninitialized();
80 break;
81 case OMIT_VALUE:
82 TTCN_Logger::log_event_str("omit");
83 break;
84 case ANY_VALUE:
85 TTCN_Logger::log_char('?');
86 break;
87 case ANY_OR_OMIT:
88 TTCN_Logger::log_char('*');
89 break;
90 default:
91 TTCN_Logger::log_event_str("<unknown template selection>");
92 break;
93 }
94}
95
96void Base_Template::log_ifpresent() const
97{
98 if (is_ifpresent) TTCN_Logger::log_event_str(" ifpresent");
99}
100
101void Base_Template::encode_text_base(Text_Buf& text_buf) const
102{
103 text_buf.push_int(template_selection);
104 text_buf.push_int(is_ifpresent);
105}
106
107void Base_Template::decode_text_base(Text_Buf& text_buf)
108{
109 template_selection = (template_sel)text_buf.pull_int().get_val();
110 is_ifpresent = (boolean)text_buf.pull_int().get_val();
111}
112
113void Base_Template::set_ifpresent()
114{
115 is_ifpresent = TRUE;
116}
117
118boolean Base_Template::is_omit() const
119{
120 return template_selection == OMIT_VALUE && !is_ifpresent;
121}
122
123boolean Base_Template::is_any_or_omit() const
124{
125 return template_selection == ANY_OR_OMIT && !is_ifpresent;
126}
127
128const char* Base_Template::get_res_name(template_res tr)
129{
130 switch (tr) {
131 case TR_VALUE: return "value";
132 case TR_OMIT: return "omit";
133 case TR_PRESENT: return "present";
134 default: break;
135 }
136 return "<unknown/invalid>";
137}
138
139void Base_Template::set_param(Module_Param& /*param*/)
140{
141 TTCN_error("Internal error: Base_Template::set_param()");
142}
143
3abe9331 144Module_Param* Base_Template::get_param(Module_Param_Name& /* param_name */) const
145{
146 TTCN_error("Internal error: Base_Template::get_param()");
147 return NULL;
148}
149
970ed795
EL
150Restricted_Length_Template::Restricted_Length_Template()
151{
152 length_restriction_type = NO_LENGTH_RESTRICTION;
153}
154
155Restricted_Length_Template::Restricted_Length_Template(template_sel other_value)
156: Base_Template(other_value)
157{
158 length_restriction_type = NO_LENGTH_RESTRICTION;
159}
160
161void Restricted_Length_Template::set_selection(template_sel other_value)
162{
163 template_selection = other_value;
164 is_ifpresent = FALSE;
165 length_restriction_type = NO_LENGTH_RESTRICTION;
166}
167
168void Restricted_Length_Template::set_selection
169(const Restricted_Length_Template& other_value)
170{
171 template_selection = other_value.template_selection;
172 is_ifpresent = other_value.is_ifpresent;
173 length_restriction_type = other_value.length_restriction_type;
174 length_restriction = other_value.length_restriction;
175}
176
177boolean Restricted_Length_Template::match_length(int value_length) const
178{
179 switch (length_restriction_type) {
180 case NO_LENGTH_RESTRICTION:
181 return TRUE;
182 case SINGLE_LENGTH_RESTRICTION:
183 return value_length == length_restriction.single_length;
184 case RANGE_LENGTH_RESTRICTION:
185 return value_length >= length_restriction.range_length.min_length &&
186 (!length_restriction.range_length.max_length_set ||
187 value_length <= length_restriction.range_length.max_length);
188 default:
189 TTCN_error("Internal error: Matching with a template that has invalid "
190 "length restriction type.");
191 }
192 return FALSE;
193}
194
195int Restricted_Length_Template::check_section_is_single(int min_size,
196 boolean has_any_or_none, const char* operation_name,
197 const char* type_name_prefix, const char* type_name) const
198{
199 if (has_any_or_none) // upper limit is infinity
200 {
201 switch (length_restriction_type)
202 {
203 case NO_LENGTH_RESTRICTION:
204 TTCN_error("Performing %sof() operation on %s %s with no exact %s.",
205 operation_name, type_name_prefix, type_name, operation_name);
206 case SINGLE_LENGTH_RESTRICTION:
207 if (length_restriction.single_length>=min_size)
208 return length_restriction.single_length;
209 TTCN_error("Performing %sof() operation on an invalid %s. "
210 "The minimum %s (%d) contradicts the "
211 "length restriction (%d).",
212 operation_name, type_name, operation_name,
213 min_size, length_restriction.single_length);
214 case RANGE_LENGTH_RESTRICTION: {
215 boolean has_invalid_restriction;
216 if (match_length(min_size))
217 {
218 if (length_restriction.range_length.max_length_set &&
219 (min_size==length_restriction.range_length.max_length))
220 return min_size;
221 has_invalid_restriction = FALSE;
222 }
223 else
224 {
225 has_invalid_restriction =
226 min_size>length_restriction.range_length.min_length;
227 }
228 if (has_invalid_restriction)
229 {
230 if (length_restriction.range_length.max_length_set)
231 TTCN_error("Performing %sof() operation on an invalid %s. "
232 "The minimum %s (%d) contradicts the "
233 "length restriction (%d..%d).",
234 operation_name, type_name, operation_name, min_size,
235 length_restriction.range_length.min_length,
236 length_restriction.range_length.max_length);
237 else
238 TTCN_error("Performing %sof() operation on an invalid %s. "
239 "The minimum %s (%d) contradicts the "
240 "length restriction (%d..infinity).",
241 operation_name, type_name, operation_name, min_size,
242 length_restriction.range_length.min_length);
243 }
244 else
245 TTCN_error("Performing %sof() operation on %s %s with no exact %s.",
246 operation_name, type_name_prefix, type_name, operation_name);
247 break; }
248
249 default:
250 TTCN_error("Internal error: Template has invalid "
251 "length restriction type.");
252 }
253 }
254 else // exact size is in min_size, check for invalid restriction
255 {
256 switch (length_restriction_type)
257 {
258 case NO_LENGTH_RESTRICTION:
259 return min_size;
260 case SINGLE_LENGTH_RESTRICTION:
261 if (length_restriction.single_length==min_size) return min_size;
262 TTCN_error("Performing %sof() operation on an invalid %s. "
263 "The %s (%d) contradicts the length restriction (%d).",
264 operation_name, type_name, operation_name, min_size,
265 length_restriction.single_length);
266 case RANGE_LENGTH_RESTRICTION:
267 if (!match_length(min_size))
268 {
269 if (length_restriction.range_length.max_length_set)
270 TTCN_error("Performing %sof() operation on an invalid %s. "
271 "The %s (%d) contradicts the length restriction (%d..%d).",
272 operation_name, type_name, operation_name, min_size,
273 length_restriction.range_length.min_length,
274 length_restriction.range_length.max_length);
275 else
276 TTCN_error("Performing %sof() operation on an invalid %s. "
277 "The %s (%d) contradicts the "
278 "length restriction (%d..infinity).",
279 operation_name, type_name, operation_name, min_size,
280 length_restriction.range_length.min_length);
281 }
282 else
283 return min_size;
284 default:
285 TTCN_error("Internal error: Template has invalid "
286 "length restriction type.");
287 }
288 }
289 return 0;
290}
291
292void Restricted_Length_Template::log_restricted() const
293{
294 switch (length_restriction_type) {
295 case SINGLE_LENGTH_RESTRICTION:
296 TTCN_Logger::log_event(" length (%d)",
297 length_restriction.single_length);
298 break;
299 case NO_LENGTH_RESTRICTION:
300 break;
301 case RANGE_LENGTH_RESTRICTION:
302 TTCN_Logger::log_event(" length (%d .. ",
303 length_restriction.range_length.min_length);
304 if (length_restriction.range_length.max_length_set)
305 TTCN_Logger::log_event("%d)",
306 length_restriction.range_length.max_length);
307 else TTCN_Logger::log_event_str("infinity)");
308 break;
309 default:
310 TTCN_Logger::log_event_str("<unknown length restriction>");
311 break;
312 }
313}
314
315void Restricted_Length_Template::log_match_length(int value_length) const
316{
317 if (length_restriction_type != NO_LENGTH_RESTRICTION) {
318 if(TTCN_Logger::VERBOSITY_COMPACT == TTCN_Logger::get_matching_verbosity()){
319 if (!match_length(value_length)){
320 TTCN_Logger::print_logmatch_buffer();
321 log_restricted();
322 TTCN_Logger::log_event(" with %d ", value_length);
323 }
324 }else{
325 log_restricted();
326 TTCN_Logger::log_event(" with %d ", value_length);
327 if (match_length(value_length)) TTCN_Logger::log_event_str("matched");
328 else TTCN_Logger::log_event_str("unmatched");
329 }
330 }
331}
332
333void Restricted_Length_Template::encode_text_restricted(Text_Buf& text_buf)const
334{
335 encode_text_base(text_buf);
336 text_buf.push_int(length_restriction_type);
337 switch (length_restriction_type) {
338 case SINGLE_LENGTH_RESTRICTION:
339 text_buf.push_int(length_restriction.single_length);
340 break;
341 case NO_LENGTH_RESTRICTION:
342 break;
343 case RANGE_LENGTH_RESTRICTION:
344 text_buf.push_int(length_restriction.range_length.min_length);
345 text_buf.push_int(length_restriction.range_length.max_length_set);
346 if (length_restriction.range_length.max_length_set)
347 text_buf.push_int(length_restriction.range_length.max_length);
348 break;
349 default:
350 TTCN_error("Text encoder: encoding an unknown/unsupported length "
351 "restriction type in a template.");
352 }
353}
354
355void Restricted_Length_Template::decode_text_restricted(Text_Buf& text_buf)
356{
357 decode_text_base(text_buf);
358 length_restriction_type = (length_restriction_type_t)
359 text_buf.pull_int().get_val();
360 switch (length_restriction_type) {
361 case SINGLE_LENGTH_RESTRICTION:
362 length_restriction.single_length = text_buf.pull_int().get_val();
363 break;
364 case NO_LENGTH_RESTRICTION:
365 break;
366 case RANGE_LENGTH_RESTRICTION:
367 length_restriction.range_length.min_length =
368 text_buf.pull_int().get_val();
369 length_restriction.range_length.max_length_set =
370 (boolean)text_buf.pull_int().get_val();
371 if (length_restriction.range_length.max_length_set)
372 length_restriction.range_length.max_length =
373 text_buf.pull_int().get_val();
374 break;
375 default:
376 TTCN_error("Text decoder: an unknown/unsupported length restriction "
377 "type was received for a template.");
378 }
379}
380
381void Restricted_Length_Template::set_length_range(const Module_Param& param)
382{
383 Module_Param_Length_Restriction* length_range = param.get_length_restriction();
384 if (length_range==NULL) {
385 length_restriction_type = NO_LENGTH_RESTRICTION;
386 return;
387 }
388 if (length_range->is_single()) {
389 length_restriction_type = SINGLE_LENGTH_RESTRICTION;
390 length_restriction.single_length = (int)(length_range->get_min());
391 } else {
392 length_restriction_type = RANGE_LENGTH_RESTRICTION;
393 length_restriction.range_length.min_length = (int)(length_range->get_min());
394 length_restriction.range_length.max_length_set = length_range->get_has_max();
395 if (length_restriction.range_length.max_length_set) {
396 length_restriction.range_length.max_length = (int)(length_range->get_max());
397 }
398 }
399}
400
3abe9331 401Module_Param_Length_Restriction* Restricted_Length_Template::get_length_range() const
402{
403 if (length_restriction_type == NO_LENGTH_RESTRICTION) {
404 return NULL;
405 }
406 Module_Param_Length_Restriction* mp_res = new Module_Param_Length_Restriction();
407 if (length_restriction_type == SINGLE_LENGTH_RESTRICTION) {
408 mp_res->set_single(length_restriction.single_length);
409 }
410 else {
411 mp_res->set_min(length_restriction.range_length.min_length);
412 if (length_restriction.range_length.max_length_set) {
413 mp_res->set_max(length_restriction.range_length.max_length);
414 }
415 }
416 return mp_res;
417}
418
970ed795
EL
419void Restricted_Length_Template::set_single_length(int single_length)
420{
421 length_restriction_type = SINGLE_LENGTH_RESTRICTION;
422 length_restriction.single_length = single_length;
423}
424
425void Restricted_Length_Template::set_min_length(int min_length)
426{
427 if (min_length < 0) TTCN_error("The lower limit for the length is negative"
428 " (%d) in a template with length restriction.", min_length);
429 length_restriction_type = RANGE_LENGTH_RESTRICTION;
430 length_restriction.range_length.min_length = min_length;
431 length_restriction.range_length.max_length_set = FALSE;
432}
433
434void Restricted_Length_Template::set_max_length(int max_length)
435{
436 if (length_restriction_type != RANGE_LENGTH_RESTRICTION)
437 TTCN_error("Internal error: Setting a maximum length for a template "
438 "the length restriction of which is not a range.");
439 if (max_length < 0) TTCN_error("The upper limit for the length is negative"
440 " (%d) in a template with length restriction.", max_length);
441 if (length_restriction.range_length.min_length > max_length)
442 TTCN_error("The upper limit for the length (%d) is smaller than the "
443 "lower limit (%d) in a template with length restriction.",
444 max_length, length_restriction.range_length.min_length);
445 length_restriction.range_length.max_length = max_length;
446 length_restriction.range_length.max_length_set = TRUE;
447}
448
449boolean Restricted_Length_Template::is_omit() const
450{
451 return template_selection == OMIT_VALUE && !is_ifpresent &&
452 length_restriction_type == NO_LENGTH_RESTRICTION;
453}
454
455boolean Restricted_Length_Template::is_any_or_omit() const
456{
457 return template_selection == ANY_OR_OMIT && !is_ifpresent &&
458 length_restriction_type == NO_LENGTH_RESTRICTION;
459}
460
461////////////////////////////////////////////////////////////////////////////////
462
463struct Record_Of_Template::Pair_of_elements{
464 unsigned int start_index, end_index; //beginning and ending index
465};
466
467Record_Of_Template::Record_Of_Template()
468{
469#ifdef TITAN_RUNTIME_2
470 err_descr = NULL;
471#endif
472 number_of_permutations = 0;
473 permutation_intervals = NULL;
474}
475
476Record_Of_Template::Record_Of_Template(template_sel other_value)
477: Restricted_Length_Template(other_value)
478{
479#ifdef TITAN_RUNTIME_2
480 err_descr = NULL;
481#endif
482 number_of_permutations = 0;
483 permutation_intervals = NULL;
484}
485
486void Record_Of_Template::clean_up_intervals()
487{
488 number_of_permutations = 0;
489 Free(permutation_intervals);
490 permutation_intervals = NULL;
491}
492
493void Record_Of_Template::set_selection(template_sel other_value)
494{
495 Restricted_Length_Template::set_selection(other_value);
496 clean_up_intervals();
497}
498
499void Record_Of_Template::set_selection(const Record_Of_Template& other_value)
500{
501 Restricted_Length_Template::set_selection(other_value);
502 clean_up_intervals();
503 if(other_value.template_selection == SPECIFIC_VALUE)
504 {
505 number_of_permutations = other_value.number_of_permutations;
506 permutation_intervals = (Pair_of_elements*) Malloc(number_of_permutations * sizeof(Pair_of_elements));
507 memcpy(permutation_intervals,other_value.permutation_intervals,number_of_permutations*sizeof(Pair_of_elements));
508 }
509}
510
511#ifdef TITAN_RUNTIME_2
512
513boolean Record_Of_Template::match_function_specific(
514 const Base_Type *value_ptr, int value_index,
3abe9331 515 const Restricted_Length_Template *template_ptr, int template_index,
516 boolean legacy)
970ed795
EL
517{
518 const Record_Of_Template* rec_tmpl_ptr = static_cast<const Record_Of_Template*>(template_ptr);
519 if (value_index >= 0) {
520 const Record_Of_Type* recof_ptr = static_cast<const Record_Of_Type*>(value_ptr);
3abe9331 521 return rec_tmpl_ptr->single_value.value_elements[template_index]->matchv(recof_ptr->get_at(value_index), legacy);
970ed795
EL
522 } else {
523 return rec_tmpl_ptr->single_value.value_elements[template_index]->is_any_or_omit();
524 }
525}
526
527void Record_Of_Template::valueofv(Base_Type* value) const
528{
529 if (template_selection != SPECIFIC_VALUE || is_ifpresent)
530 TTCN_error("Performing a valueof or send operation on a non-specific template of type %s.", get_descriptor()->name);
531 Record_Of_Type* recof_value = static_cast<Record_Of_Type*>(value);
532 recof_value->set_size(single_value.n_elements);
533 for (int elem_count = 0; elem_count < single_value.n_elements; elem_count++)
534 single_value.value_elements[elem_count]->valueofv(recof_value->get_at(elem_count));
535 recof_value->set_err_descr(err_descr);
536}
537
538void Record_Of_Template::set_value(template_sel other_value)
539{
540 check_single_selection(other_value);
541 clean_up();
542 set_selection(other_value);
543 err_descr = NULL;
544}
545
546void Record_Of_Template::clean_up()
547{
548 switch (template_selection) {
549 case SPECIFIC_VALUE:
550 for (int elem_count = 0; elem_count < single_value.n_elements; elem_count++)
551 delete single_value.value_elements[elem_count];
552 free_pointers((void**)single_value.value_elements);
553 break;
554 case VALUE_LIST:
555 case COMPLEMENTED_LIST:
556 for (int list_count = 0; list_count < value_list.n_values; list_count++)
557 delete value_list.list_value[list_count];
558 free_pointers((void**)value_list.list_value);
559 break;
560 default:
561 break;
562 }
563 template_selection = UNINITIALIZED_TEMPLATE;
564}
565
566void Record_Of_Template::copy_value(const Base_Type* other_value)
567{
568 if (!other_value->is_bound())
569 TTCN_error("Initialization of a record of template with an unbound value.");
570 const Record_Of_Type* other_recof = static_cast<const Record_Of_Type*>(other_value);
571 single_value.n_elements = other_recof->size_of();
572 single_value.value_elements = (Base_Template**)allocate_pointers(single_value.n_elements);
573 for (int elem_count = 0; elem_count < single_value.n_elements; elem_count++) {
574 single_value.value_elements[elem_count] = create_elem();
575 if (other_recof->get_at(elem_count)->is_bound()) {
576 single_value.value_elements[elem_count]->copy_value(other_recof->get_at(elem_count));
577 }
578 }
579 set_selection(SPECIFIC_VALUE);
580 err_descr = other_recof->get_err_descr();
581}
582
583void Record_Of_Template::copy_template(const Record_Of_Template& other_value)
584{
585 switch (other_value.template_selection) {
586 case SPECIFIC_VALUE:
587 single_value.n_elements = other_value.single_value.n_elements;
588 single_value.value_elements = (Base_Template**)allocate_pointers(single_value.n_elements);
589 for (int elem_count = 0; elem_count < single_value.n_elements; elem_count++) {
590 if (other_value.single_value.value_elements[elem_count]->is_bound()) {
591 single_value.value_elements[elem_count] = other_value.single_value.value_elements[elem_count]->clone();
592 } else {
593 single_value.value_elements[elem_count] = create_elem();
594 }
595 }
596 break;
597 case OMIT_VALUE:
598 case ANY_VALUE:
599 case ANY_OR_OMIT:
600 break;
601 case VALUE_LIST:
602 case COMPLEMENTED_LIST:
603 value_list.n_values = other_value.value_list.n_values;
604 value_list.list_value = (Record_Of_Template**)allocate_pointers(value_list.n_values);
605 for (int list_count = 0; list_count < value_list.n_values; list_count++) {
606 if (other_value.value_list.list_value[list_count]->is_bound()) {
607 value_list.list_value[list_count] = static_cast<Record_Of_Template*>(other_value.value_list.list_value[list_count]->clone());
608 } else {
609 value_list.list_value[list_count] = static_cast<Record_Of_Template*>(create_elem());
610 }
611 }
612 break;
613 default:
614 TTCN_error("Copying an uninitialized/unsupported record of template.");
615 break;
616 }
617 set_selection(other_value);
618 err_descr = other_value.err_descr;
619}
620
621void Record_Of_Template::copy_optional(const Base_Type* other_value)
622{
623 if (other_value->is_present()) {
624 const Record_Of_Type* other_recof = static_cast<const Record_Of_Type*>(other_value->get_opt_value());
625 copy_value(other_recof);
626 } else if (other_value->is_bound()) {
627 set_selection(OMIT_VALUE);
628 err_descr = NULL;
629 } else {
630 TTCN_error("Initialization of a record of template with an unbound optional field.");
631 }
632}
633
634Base_Template* Record_Of_Template::clone() const
635{
636 Record_Of_Template* recof = create();
637 recof->copy_template(*this);
638 return recof;
639}
640
641Record_Of_Template::~Record_Of_Template()
642{
643 clean_up_intervals();
644 clean_up();
645}
646#else
647Record_Of_Template::~Record_Of_Template()
648{
649 clean_up_intervals();
650}
651#endif
652
653void Record_Of_Template::encode_text_permutation(Text_Buf& text_buf) const
654{
655 encode_text_restricted(text_buf);
656 text_buf.push_int(number_of_permutations);
657
658 for(unsigned int i = 0; i < number_of_permutations; i++)
659 {
660 text_buf.push_int(permutation_intervals[i].start_index);
661 text_buf.push_int(permutation_intervals[i].end_index);
662 }
663}
664
665void Record_Of_Template::decode_text_permutation(Text_Buf& text_buf)
666{
667 decode_text_restricted(text_buf);
668
669 number_of_permutations = text_buf.pull_int().get_val();
670 permutation_intervals = (Pair_of_elements *)Malloc
671 (number_of_permutations * sizeof(Pair_of_elements));
672
673 for (unsigned int i = 0; i < number_of_permutations; i++)
674 {
675 permutation_intervals[i].start_index =
676 text_buf.pull_int().get_val();
677 permutation_intervals[i].end_index =
678 text_buf.pull_int().get_val();
679 }
680}
681
682void Record_Of_Template::add_permutation(unsigned int start_index, unsigned int end_index)
683{
684 if(start_index > end_index)
685 TTCN_error("wrong permutation interval settings start (%d)"
686 "can not be greater than end (%d)",start_index, end_index);
687
688 if(number_of_permutations > 0 &&
689 permutation_intervals[number_of_permutations - 1].end_index >= start_index)
690 TTCN_error("the %dth permutation overlaps the previous one", number_of_permutations);
691
692 permutation_intervals = (Pair_of_elements*)Realloc(permutation_intervals, (number_of_permutations + 1) * sizeof(Pair_of_elements));
693 permutation_intervals[number_of_permutations].start_index = start_index;
694 permutation_intervals[number_of_permutations].end_index = end_index;
695 number_of_permutations++;
696}
697
698unsigned int Record_Of_Template::get_number_of_permutations(void) const
699{
700 return number_of_permutations;
701}
702
703unsigned int Record_Of_Template::get_permutation_start(unsigned int index_value) const
704{
705 if(index_value >= number_of_permutations)
706 TTCN_error("Index overflow (%d)", index_value);
707
708 return permutation_intervals[index_value].start_index;
709}
710
711unsigned int Record_Of_Template::get_permutation_end(unsigned int index_value) const
712{
713 if(index_value >= number_of_permutations)
714 TTCN_error("Index overflow (%d)", index_value);
715
716 return permutation_intervals[index_value].end_index;
717}
718
719unsigned int Record_Of_Template::get_permutation_size(unsigned int index_value) const
720{
721 if(index_value >= number_of_permutations)
722 TTCN_error("Index overflow (%d)", index_value);
723
724 return permutation_intervals[index_value].end_index - permutation_intervals[index_value].start_index + 1;
725}
726
727boolean Record_Of_Template::permutation_starts_at(unsigned int index_value) const
728{
729 for(unsigned int i = 0; i < number_of_permutations; i++)
730 {
731 if(permutation_intervals[i].start_index == index_value)
732 return TRUE;
733 }
734
735 return FALSE;
736}
737
738boolean Record_Of_Template::permutation_ends_at(unsigned int index_value) const
739{
740 for(unsigned int i = 0; i < number_of_permutations; i++)
741 {
742 if(permutation_intervals[i].end_index == index_value)
743 return TRUE;
744 }
745
746 return FALSE;
747}
748
749#ifdef TITAN_RUNTIME_2
750
751void Record_Of_Template::substr_(int index, int returncount, Record_Of_Type* rec_of) const
752{
753 if (!is_value()) TTCN_error("The first argument of function substr() is a template of type %s with non-specific value.", get_descriptor()->name);
754 rec_of->set_val(NULL_VALUE);
755 Base_Type* this_value = rec_of->clone();
756 valueofv(this_value);
757 static_cast<Record_Of_Type*>(this_value)->substr_(index, returncount, rec_of);
758 delete this_value;
759}
760
761void Record_Of_Template::replace_(int index, int len,
762 const Record_Of_Template* repl, Record_Of_Type* rec_of) const
763{
764 if (!is_value()) TTCN_error("The first argument of function replace() is a template of type %s with non-specific value.", get_descriptor()->name);
765 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);
766 rec_of->set_val(NULL_VALUE);
767 Base_Type* this_value = rec_of->clone();
768 valueofv(this_value);
769 Base_Type* repl_value = rec_of->clone();
770 repl->valueofv(repl_value);
771 // call the replace() function of the value class instance
772 static_cast<Record_Of_Type*>(this_value)->replace_(index, len, static_cast<Record_Of_Type*>(repl_value), rec_of);
773 delete this_value;
774 delete repl_value;
775}
776
777void Record_Of_Template::replace_(int index, int len,
778 const Record_Of_Type* repl, Record_Of_Type* rec_of) const
779{
780 if (!is_value()) TTCN_error("The first argument of function replace() is a template of type %s with non-specific value.", get_descriptor()->name);
781 rec_of->set_val(NULL_VALUE);
782 Base_Type* this_value = rec_of->clone();
783 valueofv(this_value);
784 // call the replace() function of the value class instance
785 static_cast<Record_Of_Type*>(this_value)->replace_(index, len, repl, rec_of);
786 delete this_value;
787}
788
789Base_Template* Record_Of_Template::get_at(int index_value)
790{
791 if (index_value < 0)
792 TTCN_error("Accessing an element of a template for type %s using a "
793 "negative index: %d.", get_descriptor()->name, index_value);
794 switch (template_selection) {
795 case SPECIFIC_VALUE:
796 if(index_value < single_value.n_elements) break;
797 // no break
798 case OMIT_VALUE:
799 case ANY_VALUE:
800 case ANY_OR_OMIT:
801 case UNINITIALIZED_TEMPLATE:
802 set_size(index_value + 1);
803 break;
804 default:
805 TTCN_error("Accessing an element of a non-specific template for type %s.",
806 get_descriptor()->name);
807 break;
808 }
809 return single_value.value_elements[index_value];
810}
811
812Base_Template* Record_Of_Template::get_at(const INTEGER& index_value)
813{
814 if (!index_value.is_bound())
815 TTCN_error("Using an unbound integer value for indexing a template of "
816 "type %s.", get_descriptor()->name);
817 return get_at((int)index_value);
818}
819
820const Base_Template* Record_Of_Template::get_at(int index_value) const
821{
822 if (index_value < 0)
823 TTCN_error("Accessing an element of a template for type %s using "
824 "a negative index: %d.", get_descriptor()->name, index_value);
825 if (template_selection != SPECIFIC_VALUE)
826 TTCN_error("Accessing an element of a non-specific template for type %s.",
827 get_descriptor()->name);
828 if (index_value >= single_value.n_elements)
829 TTCN_error("Index overflow in a template of type %s: The index is %d, but "
830 "the template has only %d elements.", get_descriptor()->name, index_value,
831 single_value.n_elements);
832 return single_value.value_elements[index_value];
833}
834
835const Base_Template* Record_Of_Template::get_at(
836 const INTEGER& index_value) const
837{
838 if (!index_value.is_bound())
839 TTCN_error("Using an unbound integer value for indexing a template of "
840 "type %s.", get_descriptor()->name);
841 return get_at((int)index_value);
842}
843
844void Record_Of_Template::set_size(int new_size)
845{
846 if (new_size < 0)
847 TTCN_error("Internal error: Setting a negative size for a template of "
848 "type %s.", get_descriptor()->name);
849 template_sel old_selection = template_selection;
850 if (old_selection != SPECIFIC_VALUE) {
851 clean_up();
852 set_selection(SPECIFIC_VALUE);
853 single_value.n_elements = 0;
854 single_value.value_elements = NULL;
855 }
856 if (new_size > single_value.n_elements) {
857 single_value.value_elements = (Base_Template**)reallocate_pointers(
858 (void**)single_value.value_elements, single_value.n_elements, new_size);
859 if (old_selection == ANY_VALUE || old_selection == ANY_OR_OMIT) {
860 for (int elem_count = single_value.n_elements; elem_count < new_size; elem_count++) {
861 single_value.value_elements[elem_count] = create_elem();
862 single_value.value_elements[elem_count]->set_value(ANY_VALUE);
863 }
864 } else {
865 for (int elem_count = single_value.n_elements; elem_count < new_size; elem_count++)
866 single_value.value_elements[elem_count] = create_elem();
867 }
868 single_value.n_elements = new_size;
869 } else if (new_size < single_value.n_elements) {
870 for (int elem_count = new_size; elem_count < single_value.n_elements; elem_count++)
871 delete single_value.value_elements[elem_count];
872 single_value.value_elements = (Base_Template**)reallocate_pointers(
873 (void**)single_value.value_elements, single_value.n_elements, new_size);
874 single_value.n_elements = new_size;
875 }
876}
877
878int Record_Of_Template::size_of(boolean is_size) const
879{
880 const char* op_name = is_size ? "size" : "length";
881 int min_size;
882 boolean has_any_or_none;
883 if (is_ifpresent)
884 TTCN_error("Performing %sof() operation on a template of type %s "
885 "which has an ifpresent attribute.", op_name, get_descriptor()->name);
886 switch (template_selection)
887 {
888 case SPECIFIC_VALUE: {
889 min_size = 0;
890 has_any_or_none = FALSE;
891 int elem_count = single_value.n_elements;
892 if (!is_size) {
893 while (elem_count>0 && !(single_value.value_elements[elem_count-1])->is_bound())
894 elem_count--;
895 }
896 for (int i=0; i<elem_count; i++)
897 {
898 switch (((Base_Template*)single_value.value_elements[i])->get_selection())
899 {
900 case OMIT_VALUE:
901 TTCN_error("Performing %sof() operation on a template of type %s "
902 "containing omit element.", op_name, get_descriptor()->name);
903 case ANY_OR_OMIT:
904 has_any_or_none = TRUE;
905 break;
906 default:
907 min_size++;
908 break;
909 }
910 }
911 } break;
912 case OMIT_VALUE:
913 TTCN_error("Performing %sof() operation on a template of type %s"
914 " containing omit value.", op_name, get_descriptor()->name);
915 case ANY_VALUE:
916 case ANY_OR_OMIT:
917 min_size = 0;
918 has_any_or_none = TRUE;
919 break;
920 case VALUE_LIST:
921 {
922 if (value_list.n_values<1)
923 TTCN_error("Performing %sof() operation on a template of type %s "
924 "containing an empty list.", op_name, get_descriptor()->name);
925 int item_size = value_list.list_value[0]->size_of(is_size);
926 for (int i = 1; i < value_list.n_values; i++) {
927 if (value_list.list_value[i]->size_of(is_size)!=item_size)
928 TTCN_error("Performing %sof() operation on a template of type %s "
929 "containing a value list with different sizes.", op_name, get_descriptor()->name);
930 }
931 min_size = item_size;
932 has_any_or_none = FALSE;
933 break;
934 }
935 case COMPLEMENTED_LIST:
936 TTCN_error("Performing %sof() operation on a template of type %s "
937 "containing complemented list.", op_name, get_descriptor()->name);
938 default:
939 TTCN_error("Performing %sof() operation on an uninitialized/unsupported "
940 "template of type %s.", op_name, get_descriptor()->name);
941 }
942 return check_section_is_single(min_size, has_any_or_none, op_name,
943 "a template of type", get_descriptor()->name);
944}
945
946int Record_Of_Template::n_elem() const
947{
948 switch (template_selection) {
949 case SPECIFIC_VALUE:
950 return single_value.n_elements;
951
952 case COMPLEMENTED_LIST:
953 TTCN_error("Performing n_elem() operation on a template of type %s "
954 "containing complemented list.", get_descriptor()->name);
955
956 case UNINITIALIZED_TEMPLATE:
957 case OMIT_VALUE:
958 case ANY_VALUE:
959 case ANY_OR_OMIT:
960 case VALUE_LIST:
961 case VALUE_RANGE:
962 case STRING_PATTERN:
963 case SUPERSET_MATCH:
964 case SUBSET_MATCH:
965 break;
966 }
967 TTCN_error("Performing n_elem() operation on an uninitialized/unsupported "
968 "template of type %s.", get_descriptor()->name);
969}
970
3abe9331 971boolean Record_Of_Template::matchv(const Base_Type* other_value,
972 boolean legacy) const
970ed795
EL
973{
974 const Record_Of_Type* other_recof = static_cast<const Record_Of_Type*>(other_value);
975 if (!other_value->is_bound()) return FALSE;
976 int value_length = other_recof->size_of();
977 if (!match_length(value_length)) return FALSE;
978 switch (template_selection) {
979 case SPECIFIC_VALUE:
3abe9331 980 return match_record_of(other_recof, value_length, this,
981 single_value.n_elements, match_function_specific, legacy);
970ed795
EL
982 case OMIT_VALUE:
983 return FALSE;
984 case ANY_VALUE:
985 case ANY_OR_OMIT:
986 return TRUE;
987 case VALUE_LIST:
988 case COMPLEMENTED_LIST:
989 for (int list_count = 0; list_count < value_list.n_values; list_count++)
3abe9331 990 if (value_list.list_value[list_count]->matchv(other_value, legacy))
970ed795
EL
991 return template_selection == VALUE_LIST;
992 return template_selection == COMPLEMENTED_LIST;
993 default:
994 TTCN_error("Matching with an uninitialized/unsupported template of type %s.",
995 get_descriptor()->name);
996 }
997 return FALSE;
998}
999
1000boolean Record_Of_Template::is_value() const
1001{
1002 if (template_selection != SPECIFIC_VALUE || is_ifpresent) return FALSE;
1003 for (int elem_count = 0; elem_count < single_value.n_elements; elem_count++)
1004 if (!single_value.value_elements[elem_count]->is_value()) return FALSE;
1005 return TRUE;
1006}
1007
1008void Record_Of_Template::set_type(template_sel template_type, int list_length)
1009{
1010 clean_up();
1011 switch (template_type) {
1012 case VALUE_LIST:
1013 case COMPLEMENTED_LIST:
1014 value_list.n_values = list_length;
1015 value_list.list_value = (Record_Of_Template**)allocate_pointers(value_list.n_values);
1016 for (int list_count = 0; list_count < value_list.n_values; list_count++)
1017 value_list.list_value[list_count] = create();
1018 break;
1019 default:
1020 TTCN_error("Internal error: Setting an invalid type for a template of "
1021 "type %s.", get_descriptor()->name);
1022 }
1023 set_selection(template_type);
1024}
1025
1026Record_Of_Template* Record_Of_Template::get_list_item(int list_index)
1027{
1028 if (template_selection != VALUE_LIST && template_selection != COMPLEMENTED_LIST)
1029 TTCN_error("Internal error: Accessing a list element of a non-list "
1030 "template of type %s.", get_descriptor()->name);
1031 if (list_index >= value_list.n_values || list_index < 0)
1032 TTCN_error("Internal error: Index overflow in a value list template "
1033 "of type %s.", get_descriptor()->name);
1034 return value_list.list_value[list_index];
1035}
1036
1037void Record_Of_Template::log() const
1038{
1039 switch (template_selection) {
1040 case SPECIFIC_VALUE:
1041 if (single_value.n_elements > 0) {
1042 TTCN_Logger::log_event_str("{ ");
1043 for (int elem_count = 0; elem_count < single_value.n_elements; elem_count++) {
1044 if (elem_count > 0) TTCN_Logger::log_event_str(", ");
1045 if (permutation_starts_at(elem_count)) TTCN_Logger::log_event_str("permutation(");
1046 single_value.value_elements[elem_count]->log();
1047 if (permutation_ends_at(elem_count)) TTCN_Logger::log_char(')');
1048 }
1049 TTCN_Logger::log_event_str(" }");
1050 } else TTCN_Logger::log_event_str("{ }");
1051 break;
1052 case COMPLEMENTED_LIST:
1053 TTCN_Logger::log_event_str("complement ");
1054 // no break
1055 case VALUE_LIST:
1056 TTCN_Logger::log_char('(');
1057 for (int list_count = 0; list_count < value_list.n_values; list_count++) {
1058 if (list_count > 0) TTCN_Logger::log_event_str(", ");
1059 value_list.list_value[list_count]->log();
1060 }
1061 TTCN_Logger::log_char(')');
1062 break;
1063 default:
1064 log_generic();
1065 break;
1066 }
1067 log_restricted();
1068 log_ifpresent();
1069 if (err_descr) err_descr->log();
1070}
1071
3abe9331 1072void Record_Of_Template::log_matchv(const Base_Type* match_value, boolean legacy) const
970ed795
EL
1073{
1074 if (TTCN_Logger::VERBOSITY_COMPACT == TTCN_Logger::get_matching_verbosity()) {
3abe9331 1075 if (matchv(match_value, legacy)) {
970ed795
EL
1076 TTCN_Logger::print_logmatch_buffer();
1077 TTCN_Logger::log_event_str(" matched");
1078 } else {
1079 const Record_Of_Type* recof_value = static_cast<const Record_Of_Type*>(match_value);
1080 if (template_selection == SPECIFIC_VALUE &&
1081 single_value.n_elements > 0 && get_number_of_permutations() == 0 &&
1082 single_value.n_elements == recof_value->size_of()) {
1083 size_t previous_size = TTCN_Logger::get_logmatch_buffer_len();
1084 for (int elem_count = 0; elem_count < single_value.n_elements; elem_count++) {
3abe9331 1085 if(!single_value.value_elements[elem_count]->matchv(recof_value->get_at(elem_count), legacy)){
970ed795 1086 TTCN_Logger::log_logmatch_info("[%d]", elem_count);
3abe9331 1087 single_value.value_elements[elem_count]->log_matchv(recof_value->get_at(elem_count), legacy);
970ed795
EL
1088 TTCN_Logger::set_logmatch_buffer_len(previous_size);
1089 }
1090 }
1091 log_match_length(single_value.n_elements);
1092 } else {
1093 TTCN_Logger::print_logmatch_buffer();
1094 match_value->log();
1095 TTCN_Logger::log_event_str(" with ");
1096 log();
1097 TTCN_Logger::log_event_str(" unmatched");
1098 }
1099 }
1100 } else {
1101 const Record_Of_Type* recof_value = static_cast<const Record_Of_Type*>(match_value);
1102 if (template_selection == SPECIFIC_VALUE &&
1103 single_value.n_elements > 0 && get_number_of_permutations() == 0 &&
1104 single_value.n_elements == recof_value->size_of()) {
1105 TTCN_Logger::log_event_str("{ ");
1106 for (int elem_count = 0; elem_count < single_value.n_elements; elem_count++) {
1107 if (elem_count > 0) TTCN_Logger::log_event_str(", ");
3abe9331 1108 single_value.value_elements[elem_count]->log_matchv(recof_value->get_at(elem_count), legacy);
970ed795
EL
1109 }
1110 TTCN_Logger::log_event_str(" }");
1111 log_match_length(single_value.n_elements);
1112 } else {
1113 match_value->log();
1114 TTCN_Logger::log_event_str(" with ");
1115 log();
3abe9331 1116 if (matchv(match_value, legacy)) TTCN_Logger::log_event_str(" matched");
970ed795
EL
1117 else TTCN_Logger::log_event_str(" unmatched");
1118 }
1119 }
1120}
1121
1122void Record_Of_Template::encode_text(Text_Buf& text_buf) const
1123{
1124 encode_text_permutation(text_buf);
1125 switch (template_selection) {
1126 case SPECIFIC_VALUE:
1127 text_buf.push_int(single_value.n_elements);
1128 for (int elem_count = 0; elem_count < single_value.n_elements; elem_count++)
1129 single_value.value_elements[elem_count]->encode_text(text_buf);
1130 break;
1131 case OMIT_VALUE:
1132 case ANY_VALUE:
1133 case ANY_OR_OMIT:
1134 break;
1135 case VALUE_LIST:
1136 case COMPLEMENTED_LIST:
1137 text_buf.push_int(value_list.n_values);
1138 for (int list_count = 0; list_count < value_list.n_values; list_count++)
1139 value_list.list_value[list_count]->encode_text(text_buf);
1140 break;
1141 default:
1142 TTCN_error("Text encoder: Encoding an uninitialized/unsupported template "
1143 "of type %s.", get_descriptor()->name);
1144 }
1145}
1146
1147void Record_Of_Template::decode_text(Text_Buf& text_buf)
1148{
1149 clean_up();
1150 decode_text_permutation(text_buf);
1151 switch (template_selection) {
1152 case SPECIFIC_VALUE:
1153 single_value.n_elements = text_buf.pull_int().get_val();
1154 if (single_value.n_elements < 0)
1155 TTCN_error("Text decoder: Negative size was received for a template of "
1156 "type %s.", get_descriptor()->name);
1157 single_value.value_elements = (Base_Template**)allocate_pointers(single_value.n_elements);
1158 for (int elem_count = 0; elem_count < single_value.n_elements; elem_count++) {
1159 single_value.value_elements[elem_count] = create_elem();
1160 single_value.value_elements[elem_count]->decode_text(text_buf);
1161 }
1162 break;
1163 case OMIT_VALUE:
1164 case ANY_VALUE:
1165 case ANY_OR_OMIT:
1166 break;
1167 case VALUE_LIST:
1168 case COMPLEMENTED_LIST:
1169 value_list.n_values = text_buf.pull_int().get_val();
1170 value_list.list_value = (Record_Of_Template**)allocate_pointers(value_list.n_values);
1171 for (int list_count = 0; list_count < value_list.n_values; list_count++) {
1172 value_list.list_value[list_count] = create();
1173 value_list.list_value[list_count]->decode_text(text_buf);
1174 }
1175 break;
1176 default:
1177 TTCN_error("Text decoder: An unknown/unsupported selection was received "
1178 "for a template of type %s.", get_descriptor()->name);
1179 }
1180}
1181
3abe9331 1182boolean Record_Of_Template::is_present(boolean legacy /* = FALSE */) const
970ed795
EL
1183{
1184 if (template_selection==UNINITIALIZED_TEMPLATE) return FALSE;
3abe9331 1185 return !match_omit(legacy);
970ed795
EL
1186}
1187
3abe9331 1188boolean Record_Of_Template::match_omit(boolean legacy /* = FALSE */) const
970ed795
EL
1189{
1190 if (is_ifpresent) return TRUE;
1191 switch (template_selection) {
1192 case OMIT_VALUE:
1193 case ANY_OR_OMIT:
1194 return TRUE;
1195 case VALUE_LIST:
1196 case COMPLEMENTED_LIST:
3abe9331 1197 if (legacy) {
1198 // legacy behavior: 'omit' can appear in the value/complement list
1199 for (int i=0; i<value_list.n_values; i++)
1200 if (value_list.list_value[i]->match_omit())
1201 return template_selection==VALUE_LIST;
1202 return template_selection==COMPLEMENTED_LIST;
1203 }
1204 // else fall through
970ed795
EL
1205 default:
1206 return FALSE;
1207 }
1208 return FALSE;
1209}
1210
1211void Record_Of_Template::set_param(Module_Param& param)
1212{
1213 if (dynamic_cast<Module_Param_Name*>(param.get_id()) != NULL &&
1214 param.get_id()->next_name()) {
1215 // Haven't reached the end of the module parameter name
1216 // => the name refers to one of the elements, not to the whole record of
1217 char* param_field = param.get_id()->get_current_name();
1218 if (param_field[0] < '0' || param_field[0] > '9') {
1219 param.error("Unexpected record field name in module parameter, expected a valid"
1220 " index for record of template type `%s'", get_descriptor()->name);
1221 }
1222 int param_index = -1;
1223 sscanf(param_field, "%d", &param_index);
1224 get_at(param_index)->set_param(param);
1225 return;
1226 }
1227
1228 param.basic_check(Module_Param::BC_TEMPLATE|Module_Param::BC_LIST, "record of template");
3abe9331 1229
1230 Module_Param_Ptr mp = &param;
1231 if (param.get_type() == Module_Param::MP_Reference) {
1232 mp = param.get_referenced_param();
1233 }
1234
1235 switch (mp->get_type()) {
970ed795
EL
1236 case Module_Param::MP_Omit:
1237 set_value(OMIT_VALUE);
1238 break;
1239 case Module_Param::MP_Any:
1240 set_value(ANY_VALUE);
1241 break;
1242 case Module_Param::MP_AnyOrNone:
1243 set_value(ANY_OR_OMIT);
1244 break;
1245 case Module_Param::MP_List_Template:
3abe9331 1246 case Module_Param::MP_ComplementList_Template: {
1247 Record_Of_Template** list_items = (Record_Of_Template**)
1248 allocate_pointers(mp->get_size());
1249 for (size_t i = 0; i < mp->get_size(); i++) {
1250 list_items[i] = create();
1251 list_items[i]->set_param(*mp->get_elem(i));
970ed795 1252 }
3abe9331 1253 clean_up();
1254 template_selection = mp->get_type() == Module_Param::MP_List_Template ?
1255 VALUE_LIST : COMPLEMENTED_LIST;
1256 value_list.n_values = mp->get_size();
1257 value_list.list_value = list_items;
1258 break; }
970ed795 1259 case Module_Param::MP_Value_List: {
3abe9331 1260 set_size(mp->get_size()); // at least this size if there are no permutation elements, if there are then get_at() will automatically resize
970ed795 1261 int curr_idx = 0; // current index into this
3abe9331 1262 for (size_t i=0; i<mp->get_size(); ++i) {
1263 Module_Param* const curr = mp->get_elem(i);
970ed795
EL
1264 switch (curr->get_type()) {
1265 case Module_Param::MP_NotUsed:
1266 // skip this element
1267 curr_idx++;
1268 break;
1269 case Module_Param::MP_Permutation_Template: {
1270 // insert all elements from the permutation
1271 int perm_start_idx = curr_idx;
1272 for (size_t perm_i=0; perm_i<curr->get_size(); perm_i++) {
1273 get_at(curr_idx)->set_param(*(curr->get_elem(perm_i)));
1274 curr_idx++;
1275 }
1276 int perm_end_idx = curr_idx - 1;
1277 add_permutation(perm_start_idx, perm_end_idx);
1278 } break;
1279 default:
1280 get_at(curr_idx)->set_param(*curr);
1281 curr_idx++;
1282 }
1283 }
1284 } break;
1285 case Module_Param::MP_Indexed_List:
1286 if (template_selection!=SPECIFIC_VALUE) set_size(0);
3abe9331 1287 for (size_t i=0; i<mp->get_size(); ++i) {
1288 Module_Param* const current = mp->get_elem(i);
970ed795
EL
1289 get_at((int)current->get_id()->get_index())->set_param(*current);
1290 }
1291 break;
1292 default:
1293 param.type_error("record of template", get_descriptor()->name);
1294 }
3abe9331 1295 is_ifpresent = param.get_ifpresent() || mp->get_ifpresent();
1296 if (param.get_length_restriction() != NULL) {
1297 set_length_range(param);
1298 }
1299 else {
1300 set_length_range(*mp);
1301 }
970ed795
EL
1302}
1303
3abe9331 1304Module_Param* Record_Of_Template::get_param(Module_Param_Name& param_name) const
1305{
1306 if (param_name.next_name()) {
1307 // Haven't reached the end of the module parameter name
1308 // => the name refers to one of the elements, not to the whole record of
1309 char* param_field = param_name.get_current_name();
1310 if (param_field[0] < '0' || param_field[0] > '9') {
1311 TTCN_error("Unexpected record field name in module parameter reference, "
1312 "expected a valid index for record of template type `%s'",
1313 get_descriptor()->name);
1314 }
1315 int param_index = -1;
1316 sscanf(param_field, "%d", &param_index);
1317 return get_at(param_index)->get_param(param_name);
1318 }
1319 Module_Param* mp = NULL;
1320 switch (template_selection) {
1321 case UNINITIALIZED_TEMPLATE:
1322 mp = new Module_Param_Unbound();
1323 break;
1324 case OMIT_VALUE:
1325 mp = new Module_Param_Omit();
1326 break;
1327 case ANY_VALUE:
1328 mp = new Module_Param_Any();
1329 break;
1330 case ANY_OR_OMIT:
1331 mp = new Module_Param_AnyOrNone();
1332 break;
1333 case SPECIFIC_VALUE: {
1334 Vector<Module_Param*> values;
1335 for (int i = 0; i < single_value.n_elements; ++i) {
1336 values.push_back(single_value.value_elements[i]->get_param(param_name));
1337 }
1338 mp = new Module_Param_Value_List();
1339 mp->add_list_with_implicit_ids(&values);
1340 values.clear();
1341 break; }
1342 case VALUE_LIST:
1343 case COMPLEMENTED_LIST: {
1344 if (template_selection == VALUE_LIST) {
1345 mp = new Module_Param_List_Template();
1346 }
1347 else {
1348 mp = new Module_Param_ComplementList_Template();
1349 }
1350 for (int i = 0; i < value_list.n_values; ++i) {
1351 mp->add_elem(value_list.list_value[i]->get_param(param_name));
1352 }
1353 break; }
1354 default:
1355 break;
1356 }
1357 if (is_ifpresent) {
1358 mp->set_ifpresent();
1359 }
1360 mp->set_length_restriction(get_length_range());
1361 return mp;
1362}
1363
1364void Record_Of_Template::check_restriction(template_res t_res, const char* t_name,
1365 boolean legacy /* = FALSE */) const
970ed795
EL
1366{
1367 if (template_selection==UNINITIALIZED_TEMPLATE) return;
1368 switch ((t_name && (t_res==TR_VALUE)) ? TR_OMIT : t_res) {
1369 case TR_OMIT:
1370 if (template_selection==OMIT_VALUE) return;
1371 // no break
1372 case TR_VALUE:
1373 if (template_selection!=SPECIFIC_VALUE || is_ifpresent) break;
1374 for (int i=0; i<single_value.n_elements; i++)
1375 single_value.value_elements[i]->check_restriction(t_res, t_name ? t_name : get_descriptor()->name);
1376 return;
1377 case TR_PRESENT:
3abe9331 1378 if (!match_omit(legacy)) return;
970ed795
EL
1379 break;
1380 default:
1381 return;
1382 }
1383 TTCN_error("Restriction `%s' on template of type %s violated.",
1384 get_res_name(t_res), t_name ? t_name : get_descriptor()->name);
1385}
1386
1387////////////////////////////////////////////////////////////////////////////////
1388
1389void Set_Of_Template::substr_(int index, int returncount, Record_Of_Type* rec_of) const
1390{
1391 if (!is_value()) TTCN_error("The first argument of function substr() is a template of type %s with non-specific value.", get_descriptor()->name);
1392 rec_of->set_val(NULL_VALUE);
1393 Base_Type* this_value = rec_of->clone();
1394 valueofv(this_value);
1395 static_cast<Record_Of_Type*>(this_value)->substr_(index, returncount, rec_of);
1396 delete this_value;
1397}
1398
1399void Set_Of_Template::replace_(int index, int len,
1400 const Set_Of_Template* repl, Record_Of_Type* rec_of) const
1401{
1402 if (!is_value()) TTCN_error("The first argument of function replace() is a template of type %s with non-specific value.", get_descriptor()->name);
1403 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);
1404 rec_of->set_val(NULL_VALUE);
1405 Base_Type* this_value = rec_of->clone();
1406 valueofv(this_value);
1407 Base_Type* repl_value = rec_of->clone();
1408 repl->valueofv(repl_value);
1409 // call the replace() function of the value class instance
1410 static_cast<Record_Of_Type*>(this_value)->replace_(index, len, static_cast<Record_Of_Type*>(repl_value), rec_of);
1411 delete this_value;
1412 delete repl_value;
1413}
1414
1415void Set_Of_Template::replace_(int index, int len,
1416 const Record_Of_Type* repl, Record_Of_Type* rec_of) const
1417{
1418 if (!is_value()) TTCN_error("The first argument of function replace() is a template of type %s with non-specific value.", get_descriptor()->name);
1419 rec_of->set_val(NULL_VALUE);
1420 Base_Type* this_value = rec_of->clone();
1421 valueofv(this_value);
1422 // call the replace() function of the value class instance
1423 static_cast<Record_Of_Type*>(this_value)->replace_(index, len, repl, rec_of);
1424 delete this_value;
1425}
1426
1427Set_Of_Template::Set_Of_Template(): err_descr(NULL)
1428{
1429}
1430
1431Set_Of_Template::Set_Of_Template(template_sel other_value)
1432 : Restricted_Length_Template(other_value), err_descr(NULL)
1433{
1434}
1435
1436Set_Of_Template::~Set_Of_Template()
1437{
1438 clean_up();
1439}
1440
1441void Set_Of_Template::clean_up()
1442{
1443 switch (template_selection) {
1444 case SPECIFIC_VALUE:
1445 case SUPERSET_MATCH:
1446 case SUBSET_MATCH:
1447 for (int elem_count = 0; elem_count < single_value.n_elements; elem_count++)
1448 delete single_value.value_elements[elem_count];
1449 free_pointers((void**)single_value.value_elements);
1450 break;
1451 case VALUE_LIST:
1452 case COMPLEMENTED_LIST:
1453 for (int elem_count = 0; elem_count < value_list.n_values; elem_count++)
1454 delete value_list.list_value[elem_count];
1455 free_pointers((void**)value_list.list_value);
1456 break;
1457 default:
1458 break;
1459 }
1460 template_selection = UNINITIALIZED_TEMPLATE;
1461}
1462
1463void Set_Of_Template::copy_value(const Base_Type* other_value)
1464{
1465 if (!other_value->is_bound())
1466 TTCN_error("Initialization of a set of template with an unbound value.");
1467 const Record_Of_Type* other_setof = static_cast<const Record_Of_Type*>(other_value);
1468 single_value.n_elements = other_setof->size_of();
1469 single_value.value_elements = (Base_Template**)allocate_pointers(single_value.n_elements);
1470 for (int elem_count = 0; elem_count < single_value.n_elements; elem_count++) {
1471 single_value.value_elements[elem_count] = create_elem();
1472 single_value.value_elements[elem_count]->copy_value(other_setof->get_at(elem_count));
1473 }
1474 set_selection(SPECIFIC_VALUE);
1475 err_descr = other_setof->get_err_descr();
1476}
1477
1478void Set_Of_Template::copy_optional(const Base_Type* other_value)
1479{
1480 if (other_value->is_present()) {
1481 const Record_Of_Type* other_setof = static_cast<const Record_Of_Type*>(other_value->get_opt_value());
1482 copy_value(other_setof);
1483 } else if (other_value->is_bound()) {
1484 set_selection(OMIT_VALUE);
1485 err_descr = NULL;
1486 } else {
1487 TTCN_error("Initialization of a set of template with an unbound optional field.");
1488 }
1489}
1490
1491void Set_Of_Template::copy_template(const Set_Of_Template& other_value)
1492{
1493 switch (other_value.template_selection) {
1494 case SPECIFIC_VALUE:
1495 case SUPERSET_MATCH:
1496 case SUBSET_MATCH:
1497 single_value.n_elements = other_value.single_value.n_elements;
1498 single_value.value_elements = (Base_Template**)allocate_pointers(single_value.n_elements);
1499 for (int elem_count = 0; elem_count < single_value.n_elements; elem_count++)
1500 single_value.value_elements[elem_count] = other_value.single_value.value_elements[elem_count]->clone();
1501 break;
1502 case OMIT_VALUE:
1503 case ANY_VALUE:
1504 case ANY_OR_OMIT:
1505 break;
1506 case VALUE_LIST:
1507 case COMPLEMENTED_LIST:
1508 value_list.n_values = other_value.value_list.n_values;
1509 value_list.list_value = (Set_Of_Template**)allocate_pointers(value_list.n_values);
1510 for (int list_count = 0; list_count < value_list.n_values; list_count++)
1511 value_list.list_value[list_count] = static_cast<Set_Of_Template*>(other_value.value_list.list_value[list_count]->clone());
1512 break;
1513 default:
1514 TTCN_error("Copying an uninitialized/unsupported set of template");
1515 break;
1516 }
1517 set_selection(other_value);
1518 err_descr = other_value.err_descr;
1519}
1520
1521Base_Template* Set_Of_Template::clone() const
1522{
1523 Set_Of_Template* setof = create();
1524 setof->copy_template(*this);
1525 return setof;
1526}
1527
1528Base_Template* Set_Of_Template::get_at(int index_value)
1529{
1530 if (index_value < 0)
1531 TTCN_error("Accessing an element of a template for type %s using a "
1532 "negative index: %d.", get_descriptor()->name, index_value);
1533 if (template_selection != SPECIFIC_VALUE ||
1534 index_value >= single_value.n_elements) set_size(index_value + 1);
1535 return single_value.value_elements[index_value];
1536}
1537
1538Base_Template* Set_Of_Template::get_at(const INTEGER& index_value)
1539{
1540 if (!index_value.is_bound())
1541 TTCN_error("Using an unbound integer value for indexing a template of "
1542 "type %s.", get_descriptor()->name);
1543 return get_at((int)index_value);
1544}
1545
1546const Base_Template* Set_Of_Template::get_at(int index_value) const
1547{
1548 if (index_value < 0)
1549 TTCN_error("Accessing an element of a template for type %s using "
1550 "a negative index: %d.", get_descriptor()->name, index_value);
1551 if (template_selection != SPECIFIC_VALUE)
1552 TTCN_error("Accessing an element of a non-specific template for type %s.",
1553 get_descriptor()->name);
1554 if (index_value >= single_value.n_elements)
1555 TTCN_error("Index overflow in a template of type %s: The index is %d, but "
1556 "the template has only %d elements.", get_descriptor()->name,
1557 index_value, single_value.n_elements);
1558 return single_value.value_elements[index_value];
1559}
1560
1561const Base_Template* Set_Of_Template::get_at(const INTEGER& index_value) const
1562{
1563 if (!index_value.is_bound())
1564 TTCN_error("Using an unbound integer value for indexing a template of "
1565 "type %s.", get_descriptor()->name);
1566 return get_at((int)index_value);
1567}
1568
1569void Set_Of_Template::set_size(int new_size)
1570{
1571 if (new_size < 0)
1572 TTCN_error("Internal error: Setting a negative size for a template of "
1573 "type %s.", get_descriptor()->name);
1574 template_sel old_selection = template_selection;
1575 if (old_selection != SPECIFIC_VALUE) {
1576 clean_up();
1577 set_selection(SPECIFIC_VALUE);
1578 single_value.n_elements = 0;
1579 single_value.value_elements = NULL;
1580 }
1581 if (new_size > single_value.n_elements) {
1582 single_value.value_elements = (Base_Template**)reallocate_pointers((void**)
1583 single_value.value_elements, single_value.n_elements, new_size);
1584 if (old_selection == ANY_VALUE || old_selection == ANY_OR_OMIT) {
1585 for (int elem_count = single_value.n_elements;
1586 elem_count < new_size; elem_count++) {
1587 single_value.value_elements[elem_count] = create_elem();
1588 single_value.value_elements[elem_count]->set_value(ANY_VALUE);
1589 }
1590 } else {
1591 for (int elem_count = single_value.n_elements;
1592 elem_count < new_size; elem_count++)
1593 single_value.value_elements[elem_count] = create_elem();
1594 }
1595 single_value.n_elements = new_size;
1596 } else if (new_size < single_value.n_elements) {
1597 for (int elem_count = new_size;
1598 elem_count < single_value.n_elements; elem_count++)
1599 delete single_value.value_elements[elem_count];
1600 single_value.value_elements = (Base_Template**)reallocate_pointers((void**)
1601 single_value.value_elements, single_value.n_elements, new_size);
1602 single_value.n_elements = new_size;
1603 }
1604}
1605
1606int Set_Of_Template::size_of(boolean is_size) const
1607{
1608 const char* op_name = is_size ? "size" : "length";
1609 int min_size = -1;
1610 boolean has_any_or_none = FALSE;
1611 if (is_ifpresent)
1612 TTCN_error("Performing %sof() operation on a template of type %s "
1613 "which has an ifpresent attribute.", op_name, get_descriptor()->name);
1614 switch (template_selection)
1615 {
1616 case SPECIFIC_VALUE:
1617 case SUPERSET_MATCH:
1618 case SUBSET_MATCH: {
1619 min_size = 0;
1620 has_any_or_none = FALSE;
1621 int elem_count = single_value.n_elements;
1622 if (!is_size) {
1623 while (elem_count>0 && !single_value.value_elements[elem_count-1]->is_bound())
1624 elem_count--;
1625 }
1626 for (int i=0; i<elem_count; i++)
1627 {
1628 switch (single_value.value_elements[i]->get_selection())
1629 {
1630 case OMIT_VALUE:
1631 TTCN_error("Performing %sof() operation on a template of type %s "
1632 "containing omit element.", op_name, get_descriptor()->name);
1633 case ANY_OR_OMIT:
1634 has_any_or_none = TRUE;
1635 break;
1636 default:
1637 min_size++;
1638 break;
1639 }
1640 }
1641 if (template_selection==SUPERSET_MATCH)
1642 {
1643 has_any_or_none = TRUE;
1644 }
1645 else if (template_selection==SUBSET_MATCH)
1646 {
1647 int max_size = min_size;
1648 min_size = 0;
1649 if (!has_any_or_none) // [0,max_size]
1650 {
1651 switch (length_restriction_type)
1652 {
1653 case NO_LENGTH_RESTRICTION:
1654 if (max_size==0) return 0;
1655 TTCN_error("Performing %sof() operation on a template of type "
1656 "%s with no exact size.", op_name, get_descriptor()->name);
1657 case SINGLE_LENGTH_RESTRICTION:
1658 if (length_restriction.single_length<=max_size)
1659 return length_restriction.single_length;
1660 TTCN_error("Performing %sof() operation on an invalid template of "
1661 "type %s. The maximum size (%d) contradicts the length restriction "
1662 "(%d).", op_name, get_descriptor()->name, max_size,
1663 length_restriction.single_length);
1664 case RANGE_LENGTH_RESTRICTION:
1665 if (max_size==length_restriction.range_length.min_length)
1666 return max_size;
1667 else if (max_size>length_restriction.range_length.min_length)
1668 TTCN_error("Performing %sof() operation on a template of type %s "
1669 "with no exact size.", op_name, get_descriptor()->name);
1670 else
1671 TTCN_error("Performing %sof() operation on an invalid template of "
1672 "type %s. Maximum size (%d) contradicts the length restriction "
1673 "(%d..%d).", op_name, get_descriptor()->name, max_size,
1674 length_restriction.range_length.min_length,
1675 length_restriction.range_length.max_length);
1676 default:
1677 TTCN_error("Internal error: Template has invalid length restriction type.");
1678 }
1679 }
1680 }
1681 } break;
1682 case OMIT_VALUE:
1683 TTCN_error("Performing %sof() operation on a template of type %s"
1684 " containing omit value.", op_name, get_descriptor()->name);
1685 case ANY_VALUE:
1686 case ANY_OR_OMIT:
1687 min_size = 0;
1688 has_any_or_none = TRUE;
1689 break;
1690 case VALUE_LIST:
1691 {
1692 if (value_list.n_values<1)
1693 TTCN_error("Performing %sof() operation on a template of type %s "
1694 "containing an empty list.", op_name, get_descriptor()->name);
1695 int item_size = value_list.list_value[0]->size_of(is_size);
1696 for (int i = 1; i < value_list.n_values; i++) {
1697 if (value_list.list_value[i]->size_of(is_size)!=item_size)
1698 TTCN_error("Performing %sof() operation on a template of type %s "
1699 "containing a value list with different sizes.", op_name, get_descriptor()->name);
1700 }
1701 min_size = item_size;
1702 has_any_or_none = FALSE;
1703 break;
1704 }
1705 case COMPLEMENTED_LIST:
1706 TTCN_error("Performing %sof() operation on a template of type %s "
1707 "containing complemented list.", op_name, get_descriptor()->name);
1708 case UNINITIALIZED_TEMPLATE:
1709 case VALUE_RANGE:
1710 case STRING_PATTERN:
1711 TTCN_error("Performing %sof() operation on an uninitialized/unsupported "
1712 "template of type %s.", op_name, get_descriptor()->name);
1713 }
1714 return check_section_is_single(min_size, has_any_or_none, op_name,
1715 "a template of type", get_descriptor()->name);
1716}
1717
1718int Set_Of_Template::n_elem() const
1719{
1720 switch (template_selection) {
1721 case SPECIFIC_VALUE:
1722 case SUPERSET_MATCH:
1723 case SUBSET_MATCH:
1724 return single_value.n_elements;
1725
1726 case COMPLEMENTED_LIST:
1727 TTCN_error("Performing n_elem() operation on a template of type %s "
1728 "containing complemented list.", get_descriptor()->name);
1729
1730 case UNINITIALIZED_TEMPLATE:
1731 case OMIT_VALUE:
1732 case ANY_VALUE:
1733 case ANY_OR_OMIT:
1734 case VALUE_LIST:
1735 case VALUE_RANGE:
1736 case STRING_PATTERN:
1737 break;
1738 }
1739 TTCN_error("Performing n_elem() operation on an uninitialized/unsupported "
1740 "template of type %s.", get_descriptor()->name);
1741}
1742
1743boolean Set_Of_Template::match_function_specific(
1744 const Base_Type *value_ptr, int value_index,
3abe9331 1745 const Restricted_Length_Template *template_ptr, int template_index,
1746 boolean legacy)
970ed795
EL
1747{
1748 const Set_Of_Template* set_tmpl_ptr = static_cast<const Set_Of_Template*>(template_ptr);
1749 if (value_index >= 0) {
1750 const Record_Of_Type* recof_ptr = static_cast<const Record_Of_Type*>(value_ptr);
3abe9331 1751 return set_tmpl_ptr->single_value.value_elements[template_index]->matchv(recof_ptr->get_at(value_index), legacy);
970ed795
EL
1752 } else {
1753 return set_tmpl_ptr->single_value.value_elements[template_index]->is_any_or_omit();
1754 }
1755}
1756
1757boolean Set_Of_Template::match_function_set(
1758 const Base_Type *value_ptr, int value_index,
3abe9331 1759 const Restricted_Length_Template *template_ptr, int template_index,
1760 boolean legacy)
970ed795
EL
1761{
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);
3abe9331 1765 return set_tmpl_ptr->single_value.value_elements[template_index]->matchv(recof_ptr->get_at(value_index), legacy);
970ed795
EL
1766 } else {
1767 return set_tmpl_ptr->single_value.value_elements[template_index]->is_any_or_omit();
1768 }
1769}
1770
1771void Set_Of_Template::log_function(
1772 const Base_Type *value_ptr, const Restricted_Length_Template *template_ptr,
3abe9331 1773 int index_value, int index_template, boolean legacy)
970ed795
EL
1774{
1775 const Set_Of_Template* set_tmpl_ptr = static_cast<const Set_Of_Template*>(template_ptr);
1776 const Record_Of_Type* recof_ptr = static_cast<const Record_Of_Type*>(value_ptr);
1777 if (value_ptr != NULL && template_ptr != NULL)
3abe9331 1778 set_tmpl_ptr->single_value.value_elements[index_template]->log_matchv(recof_ptr->get_at(index_value), legacy);
970ed795
EL
1779 else if (value_ptr != NULL)
1780 recof_ptr->get_at(index_value)->log();
1781 else if (template_ptr != NULL)
1782 set_tmpl_ptr->single_value.value_elements[index_template]->log();
1783}
1784
3abe9331 1785boolean Set_Of_Template::matchv(const Base_Type* other_value,
1786 boolean legacy) const
970ed795
EL
1787{
1788 const Record_Of_Type* other_recof = static_cast<const Record_Of_Type*>(other_value);
1789 if (!other_recof->is_bound())
1790 TTCN_error("Matching an unbound value of type %s with a template.",
1791 other_recof->get_descriptor()->name);
1792 int value_length = other_recof->size_of();
1793 if (!match_length(value_length)) return FALSE;
1794 switch (template_selection) {
1795 case SPECIFIC_VALUE:
1796 return match_set_of(other_recof, value_length, this,
3abe9331 1797 single_value.n_elements, match_function_specific, legacy);
970ed795
EL
1798 case OMIT_VALUE:
1799 return FALSE;
1800 case ANY_VALUE:
1801 case ANY_OR_OMIT:
1802 return TRUE;
1803 case VALUE_LIST:
1804 case COMPLEMENTED_LIST:
1805 for (int list_count = 0; list_count < value_list.n_values; list_count++)
3abe9331 1806 if (value_list.list_value[list_count]->matchv(other_recof, legacy))
970ed795
EL
1807 return template_selection == VALUE_LIST;
1808 return template_selection == COMPLEMENTED_LIST;
1809 case SUPERSET_MATCH:
1810 case SUBSET_MATCH:
1811 return match_set_of(other_recof, value_length, this,
3abe9331 1812 single_value.n_elements, match_function_set, legacy);
970ed795
EL
1813 default:
1814 TTCN_error("Matching with an uninitialized/unsupported template of type %s.",
1815 get_descriptor()->name);
1816 }
1817 return FALSE;
1818}
1819
1820boolean Set_Of_Template::is_value() const
1821{
1822 if (template_selection != SPECIFIC_VALUE || is_ifpresent) return FALSE;
1823 for (int elem_count = 0; elem_count < single_value.n_elements; elem_count++)
1824 if (!single_value.value_elements[elem_count]->is_value()) return FALSE;
1825 return TRUE;
1826}
1827
1828void Set_Of_Template::valueofv(Base_Type* value) const
1829{
1830 if (template_selection != SPECIFIC_VALUE || is_ifpresent)
1831 TTCN_error("Performing a valueof or send operation on a non-specific template of type %s.", get_descriptor()->name);
1832 Record_Of_Type* setof_value = static_cast<Record_Of_Type*>(value);
1833 setof_value->set_size(single_value.n_elements);
1834 for (int elem_count = 0; elem_count < single_value.n_elements; elem_count++)
1835 single_value.value_elements[elem_count]->valueofv(setof_value->get_at(elem_count));
1836 setof_value->set_err_descr(err_descr);
1837}
1838
1839void Set_Of_Template::set_value(template_sel other_value)
1840{
1841 check_single_selection(other_value);
1842 clean_up();
1843 set_selection(other_value);
1844 err_descr = NULL;
1845}
1846
1847void Set_Of_Template::set_type(template_sel template_type, int list_length)
1848{
1849 clean_up();
1850 switch (template_type) {
1851 case VALUE_LIST:
1852 case COMPLEMENTED_LIST:
1853 value_list.n_values = list_length;
1854 value_list.list_value = (Set_Of_Template**)allocate_pointers(value_list.n_values);
1855 for (int list_count = 0; list_count < value_list.n_values; list_count++)
1856 value_list.list_value[list_count] = create();
1857 break;
1858 case SUPERSET_MATCH:
1859 case SUBSET_MATCH:
1860 single_value.n_elements = list_length;
1861 single_value.value_elements = (Base_Template**)allocate_pointers(single_value.n_elements);
1862 for (int set_count = 0; set_count < single_value.n_elements; set_count++)
1863 single_value.value_elements[set_count] = create_elem();
1864 break;
1865 default:
1866 TTCN_error("Internal error: Setting an invalid type for a template of "
1867 "type %s.", get_descriptor()->name);
1868 }
1869 set_selection(template_type);
1870}
1871
1872Set_Of_Template* Set_Of_Template::get_list_item(int list_index)
1873{
1874 if (template_selection != VALUE_LIST && template_selection != COMPLEMENTED_LIST)
1875 TTCN_error("Internal error: Accessing a list element of a non-list "
1876 "template of type %s.", get_descriptor()->name);
1877 if (list_index >= value_list.n_values || list_index < 0)
1878 TTCN_error("Internal error: Index overflow in a value list template "
1879 "of type %s.", get_descriptor()->name);
1880 return value_list.list_value[list_index];
1881}
1882
1883Base_Template* Set_Of_Template::get_set_item(int set_index)
1884{
1885 if (template_selection != SUPERSET_MATCH && template_selection != SUBSET_MATCH)
1886 TTCN_error("Internal error: Accessing a set element of a non-set "
1887 "template of type %s.", get_descriptor()->name);
1888 if (set_index >= single_value.n_elements || set_index < 0)
1889 TTCN_error("Internal error: Index overflow in a set template of "
1890 "type %s.", get_descriptor()->name);
1891 return single_value.value_elements[set_index];
1892}
1893
1894void Set_Of_Template::log() const
1895{
1896 switch (template_selection) {
1897 case SPECIFIC_VALUE:
1898 if (single_value.n_elements > 0) {
1899 TTCN_Logger::log_event_str("{ ");
1900 for (int elem_count = 0; elem_count < single_value.n_elements; elem_count++) {
1901 if (elem_count > 0) TTCN_Logger::log_event_str(", ");
1902 single_value.value_elements[elem_count]->log();
1903 }
1904 TTCN_Logger::log_event_str(" }");
1905 } else TTCN_Logger::log_event_str("{ }");
1906 break;
1907 case COMPLEMENTED_LIST:
1908 TTCN_Logger::log_event_str("complement ");
1909 // no break
1910 case VALUE_LIST:
1911 TTCN_Logger::log_char('(');
1912 for (int list_count = 0; list_count < value_list.n_values; list_count++) {
1913 if (list_count > 0) TTCN_Logger::log_event_str(", ");
1914 value_list.list_value[list_count]->log();
1915 }
1916 TTCN_Logger::log_char(')');
1917 break;
1918 case SUPERSET_MATCH:
1919 case SUBSET_MATCH:
1920 TTCN_Logger::log_event("%s(",
1921 template_selection == SUPERSET_MATCH ? "superset" : "subset");
1922 for (int set_count = 0; set_count < single_value.n_elements; set_count++) {
1923 if (set_count > 0) TTCN_Logger::log_event_str(", ");
1924 single_value.value_elements[set_count]->log();
1925 }
1926 TTCN_Logger::log_char(')');
1927 break;
1928 default:
1929 log_generic();
1930 break;
1931 }
1932 log_restricted();
1933 log_ifpresent();
1934 if (err_descr) err_descr->log();
1935}
1936
3abe9331 1937void Set_Of_Template::log_matchv(const Base_Type* match_value, boolean legacy) const
970ed795
EL
1938{
1939 if (TTCN_Logger::VERBOSITY_COMPACT == TTCN_Logger::get_matching_verbosity()) {
3abe9331 1940 if (matchv(match_value, legacy)) {
970ed795
EL
1941 TTCN_Logger::print_logmatch_buffer();
1942 TTCN_Logger::log_event_str(" matched");
1943 } else {
1944 size_t previous_size = TTCN_Logger::get_logmatch_buffer_len();
1945 if (template_selection == SPECIFIC_VALUE) {
1946 const Record_Of_Type* setof_value = static_cast<const Record_Of_Type*>(match_value);
3abe9331 1947 log_match_heuristics(setof_value, setof_value->size_of(), this,
1948 single_value.n_elements, match_function_specific, log_function, legacy);
970ed795
EL
1949 } else {
1950 if (previous_size != 0) {
1951 TTCN_Logger::print_logmatch_buffer();
1952 TTCN_Logger::set_logmatch_buffer_len(previous_size);
1953 TTCN_Logger::log_event_str(":=");
1954 }
1955 match_value->log();
1956 TTCN_Logger::log_event_str(" with ");
1957 log();
1958 TTCN_Logger::log_event_str(" unmatched");
1959 }
1960 }
1961 } else {
1962 match_value->log();
1963 TTCN_Logger::log_event_str(" with ");
1964 log();
3abe9331 1965 if (matchv(match_value, legacy)) TTCN_Logger::log_event_str(" matched");
970ed795
EL
1966 else {
1967 TTCN_Logger::log_event_str(" unmatched");
1968 if (template_selection == SPECIFIC_VALUE) {
1969 const Record_Of_Type* setof_value = static_cast<const Record_Of_Type*>(match_value);
3abe9331 1970 log_match_heuristics(setof_value, setof_value->size_of(), this,
1971 single_value.n_elements, match_function_specific, log_function, legacy);
970ed795
EL
1972 }
1973 }
1974 }
1975}
1976
1977void Set_Of_Template::encode_text(Text_Buf& text_buf) const
1978{
1979 encode_text_restricted(text_buf);
1980 switch (template_selection) {
1981 case SPECIFIC_VALUE:
1982 case SUPERSET_MATCH:
1983 case SUBSET_MATCH:
1984 text_buf.push_int(single_value.n_elements);
1985 for (int elem_count = 0; elem_count < single_value.n_elements; elem_count++)
1986 single_value.value_elements[elem_count]->encode_text(text_buf);
1987 break;
1988 case OMIT_VALUE:
1989 case ANY_VALUE:
1990 case ANY_OR_OMIT:
1991 break;
1992 case VALUE_LIST:
1993 case COMPLEMENTED_LIST:
1994 text_buf.push_int(value_list.n_values);
1995 for (int list_count = 0; list_count < value_list.n_values; list_count++)
1996 value_list.list_value[list_count]->encode_text(text_buf);
1997 break;
1998 default:
1999 TTCN_error("Text encoder: Encoding an uninitialized/unsupported template "
2000 "of type %s.", get_descriptor()->name);
2001 }
2002}
2003
2004void Set_Of_Template::decode_text(Text_Buf& text_buf)
2005{
2006 clean_up();
2007 decode_text_restricted(text_buf);
2008 switch (template_selection) {
2009 case SPECIFIC_VALUE:
2010 case SUPERSET_MATCH:
2011 case SUBSET_MATCH:
2012 single_value.n_elements = text_buf.pull_int().get_val();
2013 if (single_value.n_elements < 0)
2014 TTCN_error("Text decoder: Negative size was received for a template of "
2015 "type %s.", get_descriptor()->name);
2016 single_value.value_elements = (Base_Template**)allocate_pointers(single_value.n_elements);
2017 for (int elem_count = 0; elem_count < single_value.n_elements; elem_count++) {
2018 single_value.value_elements[elem_count] = create_elem();
2019 single_value.value_elements[elem_count]->decode_text(text_buf);
2020 }
2021 break;
2022 case OMIT_VALUE:
2023 case ANY_VALUE:
2024 case ANY_OR_OMIT:
2025 break;
2026 case VALUE_LIST:
2027 case COMPLEMENTED_LIST:
2028 value_list.n_values = text_buf.pull_int().get_val();
2029 value_list.list_value = (Set_Of_Template**)allocate_pointers(value_list.n_values);
2030 for (int list_count = 0; list_count < value_list.n_values; list_count++) {
2031 value_list.list_value[list_count] = create();
2032 value_list.list_value[list_count]->decode_text(text_buf);
2033 }
2034 break;
2035 default:
2036 TTCN_error("Text decoder: An unknown/unsupported selection was received "
2037 "for a template of type %s.", get_descriptor()->name);
2038 }
2039}
2040
3abe9331 2041boolean Set_Of_Template::is_present(boolean legacy /* = FALSE */) const
970ed795
EL
2042{
2043 if (template_selection==UNINITIALIZED_TEMPLATE) return FALSE;
3abe9331 2044 return !match_omit(legacy);
970ed795
EL
2045}
2046
3abe9331 2047boolean Set_Of_Template::match_omit(boolean legacy /* = FALSE */) const
970ed795
EL
2048{
2049 if (is_ifpresent) return TRUE;
2050 switch (template_selection) {
2051 case OMIT_VALUE:
2052 case ANY_OR_OMIT:
2053 return TRUE;
2054 case VALUE_LIST:
2055 case COMPLEMENTED_LIST:
3abe9331 2056 if (legacy) {
2057 // legacy behavior: 'omit' can appear in the value/complement list
2058 for (int i=0; i<value_list.n_values; i++)
2059 if (value_list.list_value[i]->match_omit())
2060 return template_selection==VALUE_LIST;
2061 return template_selection==COMPLEMENTED_LIST;
2062 }
2063 // else fall through
970ed795
EL
2064 default:
2065 return FALSE;
2066 }
2067 return FALSE;
2068}
2069
2070void Set_Of_Template::set_param(Module_Param& param)
2071{
2072 if (dynamic_cast<Module_Param_Name*>(param.get_id()) != NULL &&
2073 param.get_id()->next_name()) {
2074 // Haven't reached the end of the module parameter name
2075 // => the name refers to one of the elements, not to the whole record of
2076 char* param_field = param.get_id()->get_current_name();
2077 if (param_field[0] < '0' || param_field[0] > '9') {
2078 param.error("Unexpected record field name in module parameter, expected a valid"
2079 " index for set of template type `%s'", get_descriptor()->name);
2080 }
2081 int param_index = -1;
2082 sscanf(param_field, "%d", &param_index);
2083 get_at(param_index)->set_param(param);
2084 return;
2085 }
2086
2087 param.basic_check(Module_Param::BC_TEMPLATE|Module_Param::BC_LIST, "set of template");
3abe9331 2088
2089 Module_Param_Ptr mp = &param;
2090 if (param.get_type() == Module_Param::MP_Reference) {
2091 mp = param.get_referenced_param();
2092 }
2093
2094 switch (mp->get_type()) {
970ed795
EL
2095 case Module_Param::MP_Omit:
2096 set_value(OMIT_VALUE);
2097 break;
2098 case Module_Param::MP_Any:
2099 set_value(ANY_VALUE);
2100 break;
2101 case Module_Param::MP_AnyOrNone:
2102 set_value(ANY_OR_OMIT);
2103 break;
2104 case Module_Param::MP_List_Template:
3abe9331 2105 case Module_Param::MP_ComplementList_Template: {
2106 Set_Of_Template** list_items = (Set_Of_Template**)
2107 allocate_pointers(mp->get_size());
2108 for (size_t i = 0; i < mp->get_size(); i++) {
2109 list_items[i] = create();
2110 list_items[i]->set_param(*mp->get_elem(i));
970ed795 2111 }
3abe9331 2112 clean_up();
2113 template_selection = mp->get_type() == Module_Param::MP_List_Template ?
2114 VALUE_LIST : COMPLEMENTED_LIST;
2115 value_list.n_values = mp->get_size();
2116 value_list.list_value = list_items;
2117 break; }
970ed795 2118 case Module_Param::MP_Value_List:
3abe9331 2119 set_size(mp->get_size());
2120 for (size_t i=0; i<mp->get_size(); ++i) {
2121 Module_Param* const curr = mp->get_elem(i);
970ed795
EL
2122 if (curr->get_type()!=Module_Param::MP_NotUsed) {
2123 get_at(i)->set_param(*curr);
2124 }
2125 }
2126 break;
2127 case Module_Param::MP_Indexed_List:
2128 if (template_selection!=SPECIFIC_VALUE) set_size(0);
3abe9331 2129 for (size_t i=0; i<mp->get_size(); ++i) {
2130 Module_Param* const current = mp->get_elem(i);
970ed795
EL
2131 get_at((int)current->get_id()->get_index())->set_param(*current);
2132 }
2133 break;
2134 case Module_Param::MP_Superset_Template:
2135 case Module_Param::MP_Subset_Template:
3abe9331 2136 set_type(mp->get_type()==Module_Param::MP_Superset_Template ? SUPERSET_MATCH : SUBSET_MATCH, mp->get_size());
2137 for (size_t i=0; i<mp->get_size(); i++) {
2138 get_set_item((int)i)->set_param(*mp->get_elem(i));
970ed795
EL
2139 }
2140 break;
2141 default:
2142 param.type_error("set of template", get_descriptor()->name);
2143 }
3abe9331 2144 is_ifpresent = param.get_ifpresent() || mp->get_ifpresent();
2145 if (param.get_length_restriction() != NULL) {
2146 set_length_range(param);
2147 }
2148 else {
2149 set_length_range(*mp);
2150 }
2151}
2152
2153Module_Param* Set_Of_Template::get_param(Module_Param_Name& param_name) const
2154{
2155 if (param_name.next_name()) {
2156 // Haven't reached the end of the module parameter name
2157 // => the name refers to one of the elements, not to the whole record of
2158 char* param_field = param_name.get_current_name();
2159 if (param_field[0] < '0' || param_field[0] > '9') {
2160 TTCN_error("Unexpected record field name in module parameter reference, "
2161 "expected a valid index for set of template type `%s'",
2162 get_descriptor()->name);
2163 }
2164 int param_index = -1;
2165 sscanf(param_field, "%d", &param_index);
2166 return get_at(param_index)->get_param(param_name);
2167 }
2168 Module_Param* mp = NULL;
2169 switch (template_selection) {
2170 case UNINITIALIZED_TEMPLATE:
2171 mp = new Module_Param_Unbound();
2172 break;
2173 case OMIT_VALUE:
2174 mp = new Module_Param_Omit();
2175 break;
2176 case ANY_VALUE:
2177 mp = new Module_Param_Any();
2178 break;
2179 case ANY_OR_OMIT:
2180 mp = new Module_Param_AnyOrNone();
2181 break;
2182 case SPECIFIC_VALUE: {
2183 Vector<Module_Param*> values;
2184 for (int i = 0; i < single_value.n_elements; ++i) {
2185 values.push_back(single_value.value_elements[i]->get_param(param_name));
2186 }
2187 mp = new Module_Param_Value_List();
2188 mp->add_list_with_implicit_ids(&values);
2189 values.clear();
2190 break; }
2191 case VALUE_LIST:
2192 case COMPLEMENTED_LIST: {
2193 if (template_selection == VALUE_LIST) {
2194 mp = new Module_Param_List_Template();
2195 }
2196 else {
2197 mp = new Module_Param_ComplementList_Template();
2198 }
2199 for (int i = 0; i < value_list.n_values; ++i) {
2200 mp->add_elem(value_list.list_value[i]->get_param(param_name));
2201 }
2202 break; }
2203 default:
2204 break;
2205 }
2206 if (is_ifpresent) {
2207 mp->set_ifpresent();
2208 }
2209 mp->set_length_restriction(get_length_range());
2210 return mp;
970ed795
EL
2211}
2212
3abe9331 2213void Set_Of_Template::check_restriction(template_res t_res, const char* t_name,
2214 boolean legacy /* = FALSE */) const
970ed795
EL
2215{
2216 if (template_selection==UNINITIALIZED_TEMPLATE) return;
2217 switch ((t_name&&(t_res==TR_VALUE))?TR_OMIT:t_res) {
2218 case TR_OMIT:
2219 if (template_selection==OMIT_VALUE) return;
2220 // no break
2221 case TR_VALUE:
2222 if (template_selection!=SPECIFIC_VALUE || is_ifpresent) break;
2223 for (int i=0; i<single_value.n_elements; i++)
2224 single_value.value_elements[i]->check_restriction(t_res, t_name ? t_name : get_descriptor()->name);
2225 return;
2226 case TR_PRESENT:
3abe9331 2227 if (!match_omit(legacy)) return;
970ed795
EL
2228 break;
2229 default:
2230 return;
2231 }
2232 TTCN_error("Restriction `%s' on template of type %s violated.",
2233 get_res_name(t_res), t_name ? t_name : get_descriptor()->name);
2234}
2235
2236////////////////////////////////////////////////////////////////////////////////
2237
2238Record_Template::Record_Template(): Base_Template(), err_descr(NULL)
2239{
2240}
2241
2242Record_Template::Record_Template(template_sel other_value):
2243 Base_Template(other_value), err_descr(NULL)
2244{
2245 check_single_selection(other_value);
2246}
2247
2248Record_Template::~Record_Template()
2249{
2250 clean_up();
2251}
2252
2253void Record_Template::clean_up()
2254{
2255 switch (template_selection) {
2256 case SPECIFIC_VALUE:
2257 for (int elem_count = 0; elem_count < single_value.n_elements; elem_count++)
2258 delete single_value.value_elements[elem_count];
2259 free_pointers((void**)single_value.value_elements);
2260 break;
2261 case VALUE_LIST:
2262 case COMPLEMENTED_LIST:
2263 for (int elem_count = 0; elem_count < value_list.n_values; elem_count++)
2264 delete value_list.list_value[elem_count];
2265 free_pointers((void**)value_list.list_value);
2266 break;
2267 default:
2268 break;
2269 }
2270 template_selection = UNINITIALIZED_TEMPLATE;
2271}
2272
2273void Record_Template::copy_value(const Base_Type* other_value)
2274{
2275 if (!other_value->is_bound())
2276 TTCN_error("Initialization of a record/set template with an unbound value.");
2277 set_specific();
2278 const Record_Type* other_rec = static_cast<const Record_Type*>(other_value);
2279 const int* optional_indexes = other_rec->get_optional_indexes();
2280 int next_optional_idx = 0;
2281 for (int elem_count = 0; elem_count < single_value.n_elements; elem_count++) {
2282 boolean is_optional = optional_indexes && (optional_indexes[next_optional_idx]==elem_count);
2283 if (is_optional) next_optional_idx++;
2284 const Base_Type* elem_value = other_rec->get_at(elem_count);
2285 if (!elem_value->is_bound()) continue;
2286 if (is_optional) {
2287 if (elem_value->is_present()) {
2288 single_value.value_elements[elem_count]->copy_value(other_rec->get_at(elem_count)->get_opt_value());
2289 } else {
2290 single_value.value_elements[elem_count]->set_value(OMIT_VALUE);
2291 }
2292 } else {
2293 single_value.value_elements[elem_count]->copy_value(other_rec->get_at(elem_count));
2294 }
2295 }
2296 err_descr = other_rec->get_err_descr();
2297}
2298
2299void Record_Template::copy_template(const Record_Template& other_value)
2300{
2301 switch (other_value.template_selection) {
2302 case SPECIFIC_VALUE:
2303 set_specific(); // FIXME: create_elem(int elem_idx) should be used, but that's more code to generate...
2304 // single_value.n_elements = other_value.single_value.n_elements;
2305 // single_value.value_elements = (Base_Template**)allocate_pointers(single_value.n_elements);
2306 for (int elem_count = 0; elem_count < single_value.n_elements; elem_count++) {
2307 if (other_value.single_value.value_elements[elem_count]->is_bound()) {
2308 delete single_value.value_elements[elem_count]; // FIXME: unbound elements should not be created when the element is bound
2309 single_value.value_elements[elem_count] = other_value.single_value.value_elements[elem_count]->clone();
2310 }
2311 }
2312 break;
2313 case OMIT_VALUE:
2314 case ANY_VALUE:
2315 case ANY_OR_OMIT:
2316 break;
2317 case VALUE_LIST:
2318 case COMPLEMENTED_LIST:
2319 value_list.n_values = other_value.value_list.n_values;
2320 value_list.list_value = (Record_Template**)allocate_pointers(value_list.n_values);
2321 for (int list_count = 0; list_count < value_list.n_values; list_count++) {
2322 if (other_value.value_list.list_value[list_count]->is_bound()) {
2323 value_list.list_value[list_count] = static_cast<Record_Template*>(other_value.value_list.list_value[list_count]->clone());
2324 } else {
2325 value_list.list_value[list_count] = create();
2326 }
2327 }
2328 break;
2329 default:
2330 TTCN_error("Copying an uninitialized/unsupported record/set template.");
2331 break;
2332 }
2333 set_selection(other_value);
2334 err_descr = other_value.err_descr;
2335}
2336
2337void Record_Template::copy_optional(const Base_Type* other_value)
2338{
2339 if (other_value->is_present()) {
2340 const Record_Type* other_rec = static_cast<const Record_Type*>(other_value->get_opt_value());
2341 copy_value(other_rec);
2342 } else if (other_value->is_bound()) {
2343 set_selection(OMIT_VALUE);
2344 err_descr = NULL;
2345 } else {
2346 TTCN_error("Initialization of a record/set template with an unbound optional field.");
2347 }
2348}
2349
2350void Record_Template::set_type(template_sel template_type, int list_length)
2351{
2352 if (template_type != VALUE_LIST && template_type != COMPLEMENTED_LIST)
2353 TTCN_error("Setting an invalid list for a template of type %s.", get_descriptor()->name);
2354 clean_up();
2355 set_selection(template_type);
2356 value_list.n_values = list_length;
2357 value_list.list_value = (Record_Template**)allocate_pointers(value_list.n_values);
2358 for (int list_count = 0; list_count < value_list.n_values; list_count++)
2359 value_list.list_value[list_count] = create();
2360}
2361
2362Record_Template* Record_Template::get_list_item(int list_index) const
2363{
2364 if (template_selection != VALUE_LIST && template_selection != COMPLEMENTED_LIST)
2365 TTCN_error("Accessing a list element of a non-list template of type %s.", get_descriptor()->name);
2366 if (list_index >= value_list.n_values || list_index < 0)
2367 TTCN_error("Index overflow in a value list template of type %s.", get_descriptor()->name);
2368 return value_list.list_value[list_index];
2369}
2370
2371int Record_Template::size_of() const
2372{
2373 if (is_ifpresent)
2374 TTCN_error("Performing sizeof() operation on a template of type %s "
2375 "which has an ifpresent attribute.", get_descriptor()->name);
2376 switch (template_selection)
2377 {
2378 case SPECIFIC_VALUE: {
2379 int my_size = 0;
2380 for (int elem_count = 0; elem_count < single_value.n_elements; elem_count++)
2381 if (single_value.value_elements[elem_count]->is_present()) my_size++;
2382 return my_size;
2383 }
2384 case VALUE_LIST: {
2385 if (value_list.n_values<1)
2386 TTCN_error("Internal error: Performing sizeof() operation on a template of type %s containing an empty list.", get_descriptor()->name);
2387 int item_size = value_list.list_value[0]->size_of();
2388 for (int i = 1; i < value_list.n_values; i++)
2389 if (value_list.list_value[i]->size_of()!=item_size)
2390 TTCN_error("Performing sizeof() operation on a template of type %s containing a value list with different sizes.", get_descriptor()->name);
2391 return item_size;
2392 }
2393 case OMIT_VALUE:
2394 TTCN_error("Performing sizeof() operation on a template of type %s containing omit value.", get_descriptor()->name);
2395 case ANY_VALUE:
2396 case ANY_OR_OMIT:
2397 TTCN_error("Performing sizeof() operation on a template of type %s containing */? value.", get_descriptor()->name);
2398 case COMPLEMENTED_LIST:
2399 TTCN_error("Performing sizeof() operation on a template of type %s containing complemented list.", get_descriptor()->name);
2400 default:
2401 TTCN_error("Performing sizeof() operation on an uninitialized/unsupported template of type %s.", get_descriptor()->name);
2402 }
2403 return 0;
2404}
2405
2406boolean Record_Template::is_value() const
2407{
2408 if (template_selection != SPECIFIC_VALUE || is_ifpresent) return FALSE;
2409 for (int elem_count = 0; elem_count < single_value.n_elements; elem_count++) {
2410 const Base_Template* tmpl_elem = single_value.value_elements[elem_count];
2411 if (tmpl_elem->get_selection()!=OMIT_VALUE && !tmpl_elem->is_value()) return FALSE;
2412 }
2413 return TRUE;
2414}
2415
2416void Record_Template::valueofv(Base_Type* value) const
2417{
2418 if (template_selection != SPECIFIC_VALUE || is_ifpresent)
2419 TTCN_error("Performing a valueof or send operation on a non-specific template of type %s.", get_descriptor()->name);
2420 Record_Type* rec_value = static_cast<Record_Type*>(value);
2421 const int* optional_indexes = rec_value->get_optional_indexes();
2422 int next_optional_idx = 0;
2423 for (int elem_count = 0; elem_count < single_value.n_elements; elem_count++) {
2424 boolean is_optional = optional_indexes && (optional_indexes[next_optional_idx]==elem_count);
2425 if (is_optional) {
2426 if (single_value.value_elements[elem_count]->get_selection()==OMIT_VALUE) {
2427 rec_value->get_at(elem_count)->set_to_omit();
2428 } else {
2429 rec_value->get_at(elem_count)->set_to_present(); // create instance of optional value object
2430 single_value.value_elements[elem_count]->valueofv(rec_value->get_at(elem_count)->get_opt_value());
2431 }
2432 } else {
2433 single_value.value_elements[elem_count]->valueofv(rec_value->get_at(elem_count));
2434 }
2435 if (is_optional) next_optional_idx++;
2436 }
2437 rec_value->set_err_descr(err_descr);
2438}
2439
2440void Record_Template::set_value(template_sel other_value)
2441{
2442 check_single_selection(other_value);
2443 clean_up();
2444 set_selection(other_value);
2445 err_descr = NULL;
2446}
2447
2448Base_Template* Record_Template::get_at(int index_value)
2449{
2450 set_specific();
2451 if (index_value < 0 || index_value >= single_value.n_elements)
2452 TTCN_error("Internal error: accessing an element of a template of type %s using an "
2453 "invalid index: %d.", get_descriptor()->name, index_value);
2454 return single_value.value_elements[index_value];
2455}
2456
2457const Base_Template* Record_Template::get_at(int index_value) const
2458{
2459 if (index_value < 0 || index_value >= single_value.n_elements)
2460 TTCN_error("Internal error: accessing an element of a template of type %s using an "
2461 "invalid index: %d.", get_descriptor()->name, index_value);
2462 if (template_selection != SPECIFIC_VALUE)
2463 TTCN_error("Accessing field %s of a non-specific template of type %s.",
2464 fld_name(index_value), get_descriptor()->name);
2465 return single_value.value_elements[index_value];
2466}
2467
2468Base_Template* Record_Template::clone() const
2469{
2470 Record_Template* rec = create();
2471 rec->copy_template(*this);
2472 return rec;
2473}
2474
2475void Record_Template::log() const
2476{
2477 switch (template_selection) {
2478 case SPECIFIC_VALUE:
2479 if (single_value.n_elements > 0) {
2480 TTCN_Logger::log_event_str("{ ");
2481 for (int elem_count = 0; elem_count < single_value.n_elements; elem_count++) {
2482 if (elem_count > 0) TTCN_Logger::log_event_str(", ");
2483 TTCN_Logger::log_event_str(fld_name(elem_count));
2484 TTCN_Logger::log_event_str(" := ");
2485 single_value.value_elements[elem_count]->log();
2486 }
2487 TTCN_Logger::log_event_str(" }");
2488 } else TTCN_Logger::log_event_str("{ }");
2489 break;
2490 case COMPLEMENTED_LIST:
2491 TTCN_Logger::log_event_str("complement ");
2492 // no break
2493 case VALUE_LIST:
2494 TTCN_Logger::log_char('(');
2495 for (int list_count = 0; list_count < value_list.n_values; list_count++) {
2496 if (list_count > 0) TTCN_Logger::log_event_str(", ");
2497 value_list.list_value[list_count]->log();
2498 }
2499 TTCN_Logger::log_char(')');
2500 break;
2501 default:
2502 log_generic();
2503 break;
2504 }
2505 log_ifpresent();
2506 if (err_descr) err_descr->log();
2507}
2508
3abe9331 2509boolean Record_Template::matchv(const Base_Type* other_value,
2510 boolean legacy) const
970ed795
EL
2511{
2512 switch (template_selection) {
2513 case ANY_VALUE:
2514 case ANY_OR_OMIT:
2515 return TRUE;
2516 case OMIT_VALUE:
2517 return FALSE;
2518 case SPECIFIC_VALUE: {
2519 const Record_Type* other_rec = static_cast<const Record_Type*>(other_value);
2520 const int* optional_indexes = other_rec->get_optional_indexes();
2521 int next_optional_idx = 0;
2522 for (int elem_count = 0; elem_count < single_value.n_elements; elem_count++) {
2523 boolean is_optional = optional_indexes && (optional_indexes[next_optional_idx]==elem_count);
2524 const Base_Template* elem_tmpl = single_value.value_elements[elem_count];
2525 const Base_Type* elem_value = other_rec->get_at(elem_count);
2526 if (!elem_value->is_bound()) return FALSE;
2527 boolean elem_match = is_optional ?
3abe9331 2528 ( elem_value->ispresent() ? elem_tmpl->matchv(elem_value->get_opt_value(), legacy) : elem_tmpl->match_omit(legacy) ) :
2529 elem_tmpl->matchv(other_rec->get_at(elem_count), legacy);
970ed795
EL
2530 if (!elem_match) return FALSE;
2531 if (is_optional) next_optional_idx++;
2532 }
2533 } return TRUE;
2534 case VALUE_LIST:
2535 case COMPLEMENTED_LIST:
2536 for (int list_count = 0; list_count < value_list.n_values; list_count++)
3abe9331 2537 if (value_list.list_value[list_count]->matchv(other_value, legacy)) return template_selection == VALUE_LIST;
970ed795
EL
2538 return template_selection == COMPLEMENTED_LIST;
2539 default:
2540 TTCN_error("Matching an uninitialized/unsupported template of type %s.", get_descriptor()->name);
2541 }
2542 return FALSE;
2543}
2544
3abe9331 2545void Record_Template::log_matchv(const Base_Type* match_value, boolean legacy) const
970ed795
EL
2546{
2547 if (TTCN_Logger::VERBOSITY_COMPACT == TTCN_Logger::get_matching_verbosity()) {
3abe9331 2548 if (matchv(match_value, legacy)) {
970ed795
EL
2549 TTCN_Logger::print_logmatch_buffer();
2550 TTCN_Logger::log_event_str(" matched");
2551 } else {
2552 if (template_selection == SPECIFIC_VALUE) {
2553 size_t previous_size = TTCN_Logger::get_logmatch_buffer_len();
2554 const Record_Type* match_rec = static_cast<const Record_Type*>(match_value);
2555 const int* optional_indexes = match_rec->get_optional_indexes();
2556 int next_optional_idx = 0;
2557 for (int elem_count = 0; elem_count < single_value.n_elements; elem_count++) {
2558 boolean is_optional = optional_indexes && (optional_indexes[next_optional_idx]==elem_count);
2559 const Base_Template* elem_tmpl = single_value.value_elements[elem_count];
2560 const Base_Type* elem_value = match_rec->get_at(elem_count);
2561 if (is_optional) {
2562 if (elem_value->ispresent()) {
3abe9331 2563 if (!elem_tmpl->matchv(elem_value->get_opt_value(), legacy)) {
970ed795 2564 TTCN_Logger::log_logmatch_info(".%s", fld_name(elem_count));
3abe9331 2565 elem_tmpl->log_matchv(elem_value->get_opt_value(), legacy);
970ed795
EL
2566 TTCN_Logger::set_logmatch_buffer_len(previous_size);
2567 }
2568 } else {
3abe9331 2569 if (!elem_tmpl->match_omit(legacy)) {
970ed795
EL
2570 TTCN_Logger::log_logmatch_info(".%s := omit with ", fld_name(elem_count));
2571 TTCN_Logger::print_logmatch_buffer();
2572 elem_tmpl->log();
2573 TTCN_Logger::log_event_str(" unmatched");
2574 TTCN_Logger::set_logmatch_buffer_len(previous_size);
2575 }
2576 }
2577 } else {//mandatory
3abe9331 2578 if (!elem_tmpl->matchv(elem_value, legacy)) {
970ed795 2579 TTCN_Logger::log_logmatch_info(".%s", fld_name(elem_count));
3abe9331 2580 elem_tmpl->log_matchv(elem_value, legacy);
970ed795
EL
2581 TTCN_Logger::set_logmatch_buffer_len(previous_size);
2582 }
2583 }//if
2584 if (is_optional) next_optional_idx++;
2585 }//for
2586 } else {
2587 TTCN_Logger::print_logmatch_buffer();
2588 match_value->log();
2589 TTCN_Logger::log_event_str(" with ");
2590 log();
2591 TTCN_Logger::log_event_str(" unmatched");
2592 }
2593 }
2594 } else {
2595 if (template_selection == SPECIFIC_VALUE) {
2596 const Record_Type* match_rec = static_cast<const Record_Type*>(match_value);
2597 const int* optional_indexes = match_rec->get_optional_indexes();
2598 int next_optional_idx = 0;
2599 TTCN_Logger::log_event_str("{ ");
2600 for (int elem_count = 0; elem_count < single_value.n_elements; elem_count++) {
2601 boolean is_optional = optional_indexes && (optional_indexes[next_optional_idx]==elem_count);
2602 const Base_Template* elem_tmpl = single_value.value_elements[elem_count];
2603 const Base_Type* elem_value = match_rec->get_at(elem_count);
2604 if (elem_count) TTCN_Logger::log_event_str(", ");
2605 TTCN_Logger::log_event_str(fld_name(elem_count));
2606 TTCN_Logger::log_event_str(" := ");
2607 if (is_optional) {
3abe9331 2608 if (elem_value->ispresent()) elem_tmpl->log_matchv(elem_value->get_opt_value(), legacy);
970ed795
EL
2609 else {
2610 TTCN_Logger::log_event_str("omit with ");
2611 elem_tmpl->log();
3abe9331 2612 if (elem_tmpl->match_omit(legacy)) TTCN_Logger::log_event_str(" matched");
970ed795
EL
2613 else TTCN_Logger::log_event_str(" unmatched");
2614 }
2615 } else {
3abe9331 2616 elem_tmpl->log_matchv(elem_value, legacy);
970ed795
EL
2617 }
2618 if (is_optional) next_optional_idx++;
2619 }
2620 TTCN_Logger::log_event_str(" }");
2621 } else {
2622 match_value->log();
2623 TTCN_Logger::log_event_str(" with ");
2624 log();
3abe9331 2625 if (matchv(match_value, legacy)) TTCN_Logger::log_event_str(" matched");
970ed795
EL
2626 else TTCN_Logger::log_event_str(" unmatched");
2627 }
2628 }
2629}
2630
2631void Record_Template::encode_text(Text_Buf& text_buf) const
2632{
2633 encode_text_base(text_buf);
2634 switch (template_selection) {
2635 case SPECIFIC_VALUE:
2636 for (int elem_count = 0; elem_count < single_value.n_elements; elem_count++)
2637 single_value.value_elements[elem_count]->encode_text(text_buf);
2638 break;
2639 case OMIT_VALUE:
2640 case ANY_VALUE:
2641 case ANY_OR_OMIT:
2642 break;
2643 case VALUE_LIST:
2644 case COMPLEMENTED_LIST:
2645 text_buf.push_int(value_list.n_values);
2646 for (int list_count = 0; list_count < value_list.n_values; list_count++)
2647 value_list.list_value[list_count]->encode_text(text_buf);
2648 break;
2649 default:
2650 TTCN_error("Text encoder: Encoding an uninitialized/unsupported template"
2651 " of type %s.", get_descriptor()->name);
2652 }
2653}
2654
2655void Record_Template::decode_text(Text_Buf& text_buf)
2656{
2657 clean_up();
2658 decode_text_base(text_buf);
2659 switch (template_selection) {
2660 case SPECIFIC_VALUE:
2661 template_selection = UNINITIALIZED_TEMPLATE; //set_specific will set it
2662 set_specific();
2663 for (int elem_count = 0; elem_count < single_value.n_elements; elem_count++)
2664 single_value.value_elements[elem_count]->decode_text(text_buf);
2665 break;
2666 case OMIT_VALUE:
2667 case ANY_VALUE:
2668 case ANY_OR_OMIT:
2669 break;
2670 case VALUE_LIST:
2671 case COMPLEMENTED_LIST:
2672 value_list.n_values = text_buf.pull_int().get_val();
2673 value_list.list_value = (Record_Template**)allocate_pointers(value_list.n_values);
2674 for (int list_count = 0; list_count < value_list.n_values; list_count++) {
2675 value_list.list_value[list_count] = create();
2676 value_list.list_value[list_count]->decode_text(text_buf);
2677 }
2678 break;
2679 default:
2680 TTCN_error("Text decoder: An unknown/unsupported selection was received in a template of type %s.", get_descriptor()->name);
2681 }
2682}
2683
3abe9331 2684boolean Record_Template::is_present(boolean legacy /*= FALSE*/) const
970ed795
EL
2685{
2686 if (template_selection==UNINITIALIZED_TEMPLATE) return FALSE;
3abe9331 2687 return !match_omit(legacy);
970ed795
EL
2688}
2689
3abe9331 2690boolean Record_Template::match_omit(boolean legacy /*= FALSE*/) const
970ed795
EL
2691{
2692 if (is_ifpresent) return TRUE;
2693 switch (template_selection) {
2694 case OMIT_VALUE:
2695 case ANY_OR_OMIT:
2696 return TRUE;
2697 case VALUE_LIST:
2698 case COMPLEMENTED_LIST:
3abe9331 2699 if (legacy) {
2700 // legacy behavior: 'omit' can appear in the value/complement list
2701 for (int i=0; i<value_list.n_values; i++)
2702 if (value_list.list_value[i]->match_omit()) return template_selection==VALUE_LIST;
2703 return template_selection==COMPLEMENTED_LIST;
2704 }
2705 // else fall through
970ed795
EL
2706 default:
2707 return FALSE;
2708 }
2709 return FALSE;
2710}
2711
2712void Record_Template::set_param(Module_Param& param)
2713{
2714 if (dynamic_cast<Module_Param_Name*>(param.get_id()) != NULL &&
2715 param.get_id()->next_name()) {
2716 // Haven't reached the end of the module parameter name
2717 // => the name refers to one of the fields, not to the whole record
2718 char* param_field = param.get_id()->get_current_name();
2719 if (param_field[0] >= '0' && param_field[0] <= '9') {
2720 param.error("Unexpected array index in module parameter, expected a valid field"
2721 " name for record/set template type `%s'", get_descriptor()->name);
2722 }
2723 set_specific();
2724 for (int field_idx = 0; field_idx < single_value.n_elements; field_idx++) {
2725 if (strcmp(fld_name(field_idx), param_field) == 0) {
2726 single_value.value_elements[field_idx]->set_param(param);
2727 return;
2728 }
2729 }
2730 param.error("Field `%s' not found in record/set template type `%s'",
2731 param_field, get_descriptor()->name);
2732 }
2733
2734 param.basic_check(Module_Param::BC_TEMPLATE, "record/set template");
3abe9331 2735
2736 Module_Param_Ptr mp = &param;
2737 if (param.get_type() == Module_Param::MP_Reference) {
2738 mp = param.get_referenced_param();
2739 }
2740
2741 switch (mp->get_type()) {
970ed795
EL
2742 case Module_Param::MP_Omit:
2743 set_value(OMIT_VALUE);
2744 break;
2745 case Module_Param::MP_Any:
2746 set_value(ANY_VALUE);
2747 break;
2748 case Module_Param::MP_AnyOrNone:
2749 set_value(ANY_OR_OMIT);
2750 break;
2751 case Module_Param::MP_List_Template:
3abe9331 2752 case Module_Param::MP_ComplementList_Template: {
2753 Record_Template** list_items = (Record_Template**)
2754 allocate_pointers(mp->get_size());
2755 for (size_t i = 0; i < mp->get_size(); i++) {
2756 list_items[i] = create();
2757 list_items[i]->set_param(*mp->get_elem(i));
970ed795 2758 }
3abe9331 2759 clean_up();
2760 template_selection = mp->get_type() == Module_Param::MP_List_Template ?
2761 VALUE_LIST : COMPLEMENTED_LIST;
2762 value_list.n_values = mp->get_size();
2763 value_list.list_value = list_items;
2764 break; }
970ed795
EL
2765 case Module_Param::MP_Value_List:
2766 set_specific();
3abe9331 2767 if (single_value.n_elements<(int)mp->get_size()) {
2768 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());
970ed795 2769 }
3abe9331 2770 for (size_t i=0; i<mp->get_size(); i++) {
2771 Module_Param* mp_field = mp->get_elem(i);
2772 if (mp_field->get_type()!=Module_Param::MP_NotUsed) {
2773 get_at((int)i)->set_param(*mp_field);
970ed795
EL
2774 }
2775 }
2776 break;
2777 case Module_Param::MP_Assignment_List:
2778 set_specific();
3abe9331 2779 for (size_t i=0; i<mp->get_size(); ++i) {
2780 Module_Param* const current = mp->get_elem(i);
970ed795
EL
2781 bool found = false;
2782 for (int j=0; j<single_value.n_elements; ++j) {
2783 if (!strcmp(fld_name(j), current->get_id()->get_name())) {
2784 if (current->get_type()!=Module_Param::MP_NotUsed) {
2785 get_at(j)->set_param(*current);
2786 }
2787 found = true;
2788 break;
2789 }
2790 }
2791 if (!found) {
2792 current->error("Non existent field name in type %s: %s.", get_descriptor()->name, current->get_id()->get_name());
2793 }
2794 }
2795 break;
2796 default:
2797 param.type_error("record/set template", get_descriptor()->name);
2798 }
3abe9331 2799 is_ifpresent = param.get_ifpresent() || mp->get_ifpresent();
970ed795
EL
2800}
2801
3abe9331 2802Module_Param* Record_Template::get_param(Module_Param_Name& param_name) const
2803{
2804 if (param_name.next_name()) {
2805 // Haven't reached the end of the module parameter name
2806 // => the name refers to one of the fields, not to the whole record
2807 char* param_field = param_name.get_current_name();
2808 if (param_field[0] >= '0' && param_field[0] <= '9') {
2809 TTCN_error("Unexpected array index in module parameter reference, "
2810 "expected a valid field name for record/set template type `%s'",
2811 get_descriptor()->name);
2812 }
2813 for (int field_idx = 0; field_idx < single_value.n_elements; field_idx++) {
2814 if (strcmp(fld_name(field_idx), param_field) == 0) {
2815 return get_at(field_idx)->get_param(param_name);
2816 }
2817 }
2818 TTCN_error("Field `%s' not found in record/set type `%s'",
2819 param_field, get_descriptor()->name);
2820 }
2821 Module_Param* mp = NULL;
2822 switch (template_selection) {
2823 case UNINITIALIZED_TEMPLATE:
2824 mp = new Module_Param_Unbound();
2825 break;
2826 case OMIT_VALUE:
2827 mp = new Module_Param_Omit();
2828 break;
2829 case ANY_VALUE:
2830 mp = new Module_Param_Any();
2831 break;
2832 case ANY_OR_OMIT:
2833 mp = new Module_Param_AnyOrNone();
2834 break;
2835 case SPECIFIC_VALUE: {
2836 mp = new Module_Param_Assignment_List();
2837 for (int i = 0; i < single_value.n_elements; ++i) {
2838 Module_Param* mp_field = get_at(i)->get_param(param_name);
2839 mp_field->set_id(new Module_Param_FieldName(mcopystr(fld_name(i))));
2840 mp->add_elem(mp_field);
2841 }
2842 break; }
2843 case VALUE_LIST:
2844 case COMPLEMENTED_LIST: {
2845 if (template_selection == VALUE_LIST) {
2846 mp = new Module_Param_List_Template();
2847 }
2848 else {
2849 mp = new Module_Param_ComplementList_Template();
2850 }
2851 for (int i = 0; i < value_list.n_values; ++i) {
2852 mp->add_elem(value_list.list_value[i]->get_param(param_name));
2853 }
2854 break; }
2855 default:
2856 break;
2857 }
2858 if (is_ifpresent) {
2859 mp->set_ifpresent();
2860 }
2861 return mp;
2862}
2863
2864void Record_Template::check_restriction(template_res t_res, const char* t_name,
2865 boolean legacy /* = FALSE */) const
970ed795
EL
2866{
2867 if (template_selection==UNINITIALIZED_TEMPLATE) return;
2868 switch ((t_name&&(t_res==TR_VALUE))?TR_OMIT:t_res) {
2869 case TR_OMIT:
2870 if (template_selection==OMIT_VALUE) return;
2871 // no break
2872 case TR_VALUE:
2873 if (template_selection!=SPECIFIC_VALUE || is_ifpresent) break;
2874 for (int i=0; i<single_value.n_elements; i++)
2875 single_value.value_elements[i]->check_restriction(t_res, t_name ? t_name : get_descriptor()->name);
2876 return;
2877 case TR_PRESENT:
3abe9331 2878 if (!match_omit(legacy)) return;
970ed795
EL
2879 break;
2880 default:
2881 return;
2882 }
2883 TTCN_error("Restriction `%s' on template of type %s violated.",
2884 get_res_name(t_res), t_name ? t_name : get_descriptor()->name);
2885}
2886
2887////////////////////////////////////////////////////////////////////////////////
2888
2889Empty_Record_Template::Empty_Record_Template(): Base_Template()
2890{
2891}
2892
2893Empty_Record_Template::Empty_Record_Template(template_sel other_value):
2894 Base_Template(other_value)
2895{
2896 check_single_selection(other_value);
2897}
2898
2899Empty_Record_Template::~Empty_Record_Template()
2900{
2901 clean_up();
2902}
2903
2904void Empty_Record_Template::clean_up()
2905{
2906 switch (template_selection) {
2907 case VALUE_LIST:
2908 case COMPLEMENTED_LIST:
2909 for (int elem_count = 0; elem_count < value_list.n_values; elem_count++)
2910 delete value_list.list_value[elem_count];
2911 free_pointers((void**)value_list.list_value);
2912 break;
2913 default:
2914 break;
2915 }
2916 template_selection = UNINITIALIZED_TEMPLATE;
2917}
2918
2919void Empty_Record_Template::copy_value(const Base_Type* other_value)
2920{
2921 if (!other_value->is_bound())
2922 TTCN_error("Initialization of a record/set template with an unbound value.");
2923 set_selection(SPECIFIC_VALUE);
2924}
2925
2926void Empty_Record_Template::copy_template(const Empty_Record_Template& other_value)
2927{
2928 switch (other_value.template_selection) {
2929 case SPECIFIC_VALUE:
2930 case OMIT_VALUE:
2931 case ANY_VALUE:
2932 case ANY_OR_OMIT:
2933 break;
2934 case VALUE_LIST:
2935 case COMPLEMENTED_LIST:
2936 value_list.n_values = other_value.value_list.n_values;
2937 value_list.list_value = (Empty_Record_Template**)allocate_pointers(value_list.n_values);
2938 for (int list_count = 0; list_count < value_list.n_values; list_count++)
2939 value_list.list_value[list_count] = static_cast<Empty_Record_Template*>(other_value.value_list.list_value[list_count]->clone());
2940 break;
2941 default:
2942 TTCN_error("Copying an uninitialized/unsupported record/set template.");
2943 break;
2944 }
2945 set_selection(other_value);
2946}
2947
2948void Empty_Record_Template::copy_optional(const Base_Type* other_value)
2949{
2950 if (other_value->is_present()) {
2951 const Empty_Record_Type* other_rec = static_cast<const Empty_Record_Type*>(other_value->get_opt_value());
2952 copy_value(other_rec);
2953 } else if (other_value->is_bound()) {
2954 set_selection(OMIT_VALUE);
2955 } else {
2956 TTCN_error("Initialization of a record/set template with an unbound optional field.");
2957 }
2958}
2959
2960void Empty_Record_Template::set_type(template_sel template_type, int list_length)
2961{
2962 if (template_type != VALUE_LIST && template_type != COMPLEMENTED_LIST)
2963 TTCN_error("Setting an invalid list for a template of type %s.", get_descriptor()->name);
2964 clean_up();
2965 set_selection(template_type);
2966 value_list.n_values = list_length;
2967 value_list.list_value = (Empty_Record_Template**)allocate_pointers(value_list.n_values);
2968 for (int list_count = 0; list_count < value_list.n_values; list_count++)
2969 value_list.list_value[list_count] = create();
2970}
2971
2972Empty_Record_Template* Empty_Record_Template::get_list_item(int list_index) const
2973{
2974 if (template_selection != VALUE_LIST && template_selection != COMPLEMENTED_LIST)
2975 TTCN_error("Accessing a list element of a non-list template of type %s.", get_descriptor()->name);
2976 if (list_index >= value_list.n_values || list_index < 0)
2977 TTCN_error("Index overflow in a value list template of type %s.", get_descriptor()->name);
2978 return value_list.list_value[list_index];
2979}
2980
2981int Empty_Record_Template::size_of() const
2982{
2983 if (is_ifpresent)
2984 TTCN_error("Performing sizeof() operation on a template of type %s "
2985 "which has an ifpresent attribute.", get_descriptor()->name);
2986 switch (template_selection)
2987 {
2988 case SPECIFIC_VALUE:
2989 return 0;
2990 case VALUE_LIST: {
2991 if (value_list.n_values<1)
2992 TTCN_error("Internal error: Performing sizeof() operation on a template of type %s containing an empty list.", get_descriptor()->name);
2993 int item_size = value_list.list_value[0]->size_of();
2994 for (int i = 1; i < value_list.n_values; i++)
2995 if (value_list.list_value[i]->size_of()!=item_size)
2996 TTCN_error("Performing sizeof() operation on a template of type %s containing a value list with different sizes.", get_descriptor()->name);
2997 return item_size;
2998 }
2999 case OMIT_VALUE:
3000 TTCN_error("Performing sizeof() operation on a template of type %s containing omit value.", get_descriptor()->name);
3001 case ANY_VALUE:
3002 case ANY_OR_OMIT:
3003 TTCN_error("Performing sizeof() operation on a template of type %s containing */? value.", get_descriptor()->name);
3004 case COMPLEMENTED_LIST:
3005 TTCN_error("Performing sizeof() operation on a template of type %s containing complemented list.", get_descriptor()->name);
3006 default:
3007 TTCN_error("Performing sizeof() operation on an uninitialized/unsupported template of type %s.", get_descriptor()->name);
3008 }
3009 return 0;
3010}
3011
3012boolean Empty_Record_Template::is_value() const
3013{
3014 return (template_selection == SPECIFIC_VALUE && !is_ifpresent);
3015}
3016
3017void Empty_Record_Template::valueofv(Base_Type* value) const
3018{
3019 if (template_selection != SPECIFIC_VALUE || is_ifpresent)
3020 TTCN_error("Performing a valueof or send operation on a non-specific template of type %s.", get_descriptor()->name);
3021 Empty_Record_Type* rec_value = static_cast<Empty_Record_Type*>(value);
3022 rec_value->set_null();
3023}
3024
3025void Empty_Record_Template::set_value(template_sel other_value)
3026{
3027 check_single_selection(other_value);
3028 clean_up();
3029 set_selection(other_value);
3030}
3031
3032Base_Template* Empty_Record_Template::clone() const
3033{
3034 Empty_Record_Template* rec = create();
3035 rec->copy_template(*this);
3036 return rec;
3037}
3038
3039void Empty_Record_Template::log() const
3040{
3041 switch (template_selection) {
3042 case SPECIFIC_VALUE:
3043 TTCN_Logger::log_event_str("{ }");
3044 break;
3045 case COMPLEMENTED_LIST:
3046 TTCN_Logger::log_event_str("complement ");
3047 // no break
3048 case VALUE_LIST:
3049 TTCN_Logger::log_char('(');
3050 for (int list_count = 0; list_count < value_list.n_values; list_count++) {
3051 if (list_count > 0) TTCN_Logger::log_event_str(", ");
3052 value_list.list_value[list_count]->log();
3053 }
3054 TTCN_Logger::log_char(')');
3055 break;
3056 default:
3057 log_generic();
3058 break;
3059 }
3060 log_ifpresent();
3061}
3062
3abe9331 3063boolean Empty_Record_Template::matchv(const Base_Type* other_value,
3064 boolean legacy) const
970ed795
EL
3065{
3066 switch (template_selection) {
3067 case ANY_VALUE:
3068 case ANY_OR_OMIT:
3069 return TRUE;
3070 case OMIT_VALUE:
3071 return FALSE;
3072 case SPECIFIC_VALUE:
3073 return TRUE;
3074 case VALUE_LIST:
3075 case COMPLEMENTED_LIST:
3076 for (int list_count = 0; list_count < value_list.n_values; list_count++)
3abe9331 3077 if (value_list.list_value[list_count]->matchv(other_value, legacy)) return template_selection == VALUE_LIST;
970ed795
EL
3078 return template_selection == COMPLEMENTED_LIST;
3079 default:
3080 TTCN_error("Matching an uninitialized/unsupported template of type %s.", get_descriptor()->name);
3081 }
3082 return FALSE;
3083}
3084
3abe9331 3085void Empty_Record_Template::log_matchv(const Base_Type* match_value, boolean legacy) const
970ed795
EL
3086{
3087 match_value->log();
3088 TTCN_Logger::log_event_str(" with ");
3089 log();
3abe9331 3090 if (matchv(match_value, legacy)) TTCN_Logger::log_event_str(" matched");
970ed795
EL
3091 else TTCN_Logger::log_event_str(" unmatched");
3092}
3093
3094void Empty_Record_Template::encode_text(Text_Buf& text_buf) const
3095{
3096 encode_text_base(text_buf);
3097 switch (template_selection) {
3098 case SPECIFIC_VALUE:
3099 case OMIT_VALUE:
3100 case ANY_VALUE:
3101 case ANY_OR_OMIT:
3102 break;
3103 case VALUE_LIST:
3104 case COMPLEMENTED_LIST:
3105 text_buf.push_int(value_list.n_values);
3106 for (int list_count = 0; list_count < value_list.n_values; list_count++)
3107 value_list.list_value[list_count]->encode_text(text_buf);
3108 break;
3109 default:
3110 TTCN_error("Text encoder: Encoding an uninitialized/unsupported template of type %s.", get_descriptor()->name);
3111 }
3112}
3113
3114void Empty_Record_Template::decode_text(Text_Buf& text_buf)
3115{
3116 clean_up();
3117 decode_text_base(text_buf);
3118 switch (template_selection) {
3119 case SPECIFIC_VALUE:
3120 case OMIT_VALUE:
3121 case ANY_VALUE:
3122 case ANY_OR_OMIT:
3123 break;
3124 case VALUE_LIST:
3125 case COMPLEMENTED_LIST:
3126 value_list.n_values = text_buf.pull_int().get_val();
3127 value_list.list_value = (Empty_Record_Template**)allocate_pointers(value_list.n_values);
3128 for (int list_count = 0; list_count < value_list.n_values; list_count++) {
3129 value_list.list_value[list_count] = create();
3130 value_list.list_value[list_count]->decode_text(text_buf);
3131 }
3132 break;
3133 default:
3134 TTCN_error("Text decoder: An unknown/unsupported selection was received in a template of type %s.", get_descriptor()->name);
3135 }
3136}
3137
3abe9331 3138boolean Empty_Record_Template::is_present(boolean legacy /*= FALSE*/) const
970ed795
EL
3139{
3140 if (template_selection==UNINITIALIZED_TEMPLATE) return FALSE;
3abe9331 3141 return !match_omit(legacy);
970ed795
EL
3142}
3143
3abe9331 3144boolean Empty_Record_Template::match_omit(boolean legacy /* = FALSE */) const
970ed795
EL
3145{
3146 if (is_ifpresent) return TRUE;
3147 switch (template_selection) {
3148 case OMIT_VALUE:
3149 case ANY_OR_OMIT:
3150 return TRUE;
3151 case VALUE_LIST:
3152 case COMPLEMENTED_LIST:
3abe9331 3153 if (legacy) {
3154 // legacy behavior: 'omit' can appear in the value/complement list
3155 for (int i=0; i<value_list.n_values; i++)
3156 if (value_list.list_value[i]->match_omit()) return template_selection==VALUE_LIST;
3157 return template_selection==COMPLEMENTED_LIST;
3158 }
3159 // else fall through
970ed795
EL
3160 default:
3161 return FALSE;
3162 }
3163 return FALSE;
3164}
3165
3166void Empty_Record_Template::set_param(Module_Param& param)
3167{
3168 param.basic_check(Module_Param::BC_TEMPLATE, "empty record/set template");
3abe9331 3169 Module_Param_Ptr mp = &param;
3170 if (param.get_type() == Module_Param::MP_Reference) {
3171 mp = param.get_referenced_param();
3172 }
3173 switch (mp->get_type()) {
970ed795
EL
3174 case Module_Param::MP_Omit:
3175 set_value(OMIT_VALUE);
3176 break;
3177 case Module_Param::MP_Any:
3178 set_value(ANY_VALUE);
3179 break;
3180 case Module_Param::MP_AnyOrNone:
3181 set_value(ANY_OR_OMIT);
3182 break;
3183 case Module_Param::MP_List_Template:
3abe9331 3184 case Module_Param::MP_ComplementList_Template: {
3185 Empty_Record_Template** list_items = (Empty_Record_Template**)
3186 allocate_pointers(mp->get_size());
3187 for (size_t i = 0; i < mp->get_size(); i++) {
3188 list_items[i] = create();
3189 list_items[i]->set_param(*mp->get_elem(i));
970ed795 3190 }
3abe9331 3191 clean_up();
3192 template_selection = mp->get_type() == Module_Param::MP_List_Template ?
3193 VALUE_LIST : COMPLEMENTED_LIST;
3194 value_list.n_values = mp->get_size();
3195 value_list.list_value = list_items;
3196 break; }
970ed795 3197 case Module_Param::MP_Value_List:
3abe9331 3198 if (mp->get_size()==0) {
3199 set_selection(SPECIFIC_VALUE);
3200 }
970ed795
EL
3201 else param.type_error("empty record/set template", get_descriptor()->name);
3202 break;
3203 default:
3204 param.type_error("empty record/set template", get_descriptor()->name);
3205 }
3abe9331 3206 is_ifpresent = param.get_ifpresent() || mp->get_ifpresent();
3207}
3208
3209Module_Param* Empty_Record_Template::get_param(Module_Param_Name& param_name) const
3210{
3211 Module_Param* mp = NULL;
3212 switch (template_selection) {
3213 case UNINITIALIZED_TEMPLATE:
3214 mp = new Module_Param_Unbound();
3215 break;
3216 case OMIT_VALUE:
3217 mp = new Module_Param_Omit();
3218 break;
3219 case ANY_VALUE:
3220 mp = new Module_Param_Any();
3221 break;
3222 case ANY_OR_OMIT:
3223 mp = new Module_Param_AnyOrNone();
3224 break;
3225 case SPECIFIC_VALUE:
3226 mp = new Module_Param_Value_List();
3227 break;
3228 case VALUE_LIST:
3229 case COMPLEMENTED_LIST: {
3230 if (template_selection == VALUE_LIST) {
3231 mp = new Module_Param_List_Template();
3232 }
3233 else {
3234 mp = new Module_Param_ComplementList_Template();
3235 }
3236 for (int i = 0; i < value_list.n_values; ++i) {
3237 mp->add_elem(value_list.list_value[i]->get_param(param_name));
3238 }
3239 break; }
3240 default:
3241 break;
3242 }
3243 if (is_ifpresent) {
3244 mp->set_ifpresent();
3245 }
3246 return mp;
970ed795
EL
3247}
3248
3249#endif
This page took 0.174891 seconds and 5 git commands to generate.