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