Merge pull request #83 from eadrkir/master
[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 case DECODE_MATCH:
977 break;
978 }
979 TTCN_error("Performing n_elem() operation on an uninitialized/unsupported "
980 "template of type %s.", get_descriptor()->name);
981 }
982
983 boolean Record_Of_Template::matchv(const Base_Type* other_value,
984 boolean legacy) const
985 {
986 const Record_Of_Type* other_recof = static_cast<const Record_Of_Type*>(other_value);
987 if (!other_value->is_bound()) return FALSE;
988 int value_length = other_recof->size_of();
989 if (!match_length(value_length)) return FALSE;
990 switch (template_selection) {
991 case SPECIFIC_VALUE:
992 return match_record_of(other_recof, value_length, this,
993 single_value.n_elements, match_function_specific, legacy);
994 case OMIT_VALUE:
995 return FALSE;
996 case ANY_VALUE:
997 case ANY_OR_OMIT:
998 return TRUE;
999 case VALUE_LIST:
1000 case COMPLEMENTED_LIST:
1001 for (int list_count = 0; list_count < value_list.n_values; list_count++)
1002 if (value_list.list_value[list_count]->matchv(other_value, legacy))
1003 return template_selection == VALUE_LIST;
1004 return template_selection == COMPLEMENTED_LIST;
1005 default:
1006 TTCN_error("Matching with an uninitialized/unsupported template of type %s.",
1007 get_descriptor()->name);
1008 }
1009 return FALSE;
1010 }
1011
1012 boolean Record_Of_Template::is_value() const
1013 {
1014 if (template_selection != SPECIFIC_VALUE || is_ifpresent) return FALSE;
1015 for (int elem_count = 0; elem_count < single_value.n_elements; elem_count++)
1016 if (!single_value.value_elements[elem_count]->is_value()) return FALSE;
1017 return TRUE;
1018 }
1019
1020 void Record_Of_Template::set_type(template_sel template_type, int list_length)
1021 {
1022 clean_up();
1023 switch (template_type) {
1024 case VALUE_LIST:
1025 case COMPLEMENTED_LIST:
1026 value_list.n_values = list_length;
1027 value_list.list_value = (Record_Of_Template**)allocate_pointers(value_list.n_values);
1028 for (int list_count = 0; list_count < value_list.n_values; list_count++)
1029 value_list.list_value[list_count] = create();
1030 break;
1031 default:
1032 TTCN_error("Internal error: Setting an invalid type for a template of "
1033 "type %s.", get_descriptor()->name);
1034 }
1035 set_selection(template_type);
1036 }
1037
1038 Record_Of_Template* Record_Of_Template::get_list_item(int list_index)
1039 {
1040 if (template_selection != VALUE_LIST && template_selection != COMPLEMENTED_LIST)
1041 TTCN_error("Internal error: Accessing a list element of a non-list "
1042 "template of type %s.", get_descriptor()->name);
1043 if (list_index >= value_list.n_values || list_index < 0)
1044 TTCN_error("Internal error: Index overflow in a value list template "
1045 "of type %s.", get_descriptor()->name);
1046 return value_list.list_value[list_index];
1047 }
1048
1049 void Record_Of_Template::log() const
1050 {
1051 switch (template_selection) {
1052 case SPECIFIC_VALUE:
1053 if (single_value.n_elements > 0) {
1054 TTCN_Logger::log_event_str("{ ");
1055 for (int elem_count = 0; elem_count < single_value.n_elements; elem_count++) {
1056 if (elem_count > 0) TTCN_Logger::log_event_str(", ");
1057 if (permutation_starts_at(elem_count)) TTCN_Logger::log_event_str("permutation(");
1058 single_value.value_elements[elem_count]->log();
1059 if (permutation_ends_at(elem_count)) TTCN_Logger::log_char(')');
1060 }
1061 TTCN_Logger::log_event_str(" }");
1062 } else TTCN_Logger::log_event_str("{ }");
1063 break;
1064 case COMPLEMENTED_LIST:
1065 TTCN_Logger::log_event_str("complement ");
1066 // no break
1067 case VALUE_LIST:
1068 TTCN_Logger::log_char('(');
1069 for (int list_count = 0; list_count < value_list.n_values; list_count++) {
1070 if (list_count > 0) TTCN_Logger::log_event_str(", ");
1071 value_list.list_value[list_count]->log();
1072 }
1073 TTCN_Logger::log_char(')');
1074 break;
1075 default:
1076 log_generic();
1077 break;
1078 }
1079 log_restricted();
1080 log_ifpresent();
1081 if (err_descr) err_descr->log();
1082 }
1083
1084 void Record_Of_Template::log_matchv(const Base_Type* match_value, boolean legacy) const
1085 {
1086 if (TTCN_Logger::VERBOSITY_COMPACT == TTCN_Logger::get_matching_verbosity()) {
1087 if (matchv(match_value, legacy)) {
1088 TTCN_Logger::print_logmatch_buffer();
1089 TTCN_Logger::log_event_str(" matched");
1090 } else {
1091 const Record_Of_Type* recof_value = static_cast<const Record_Of_Type*>(match_value);
1092 if (template_selection == SPECIFIC_VALUE &&
1093 single_value.n_elements > 0 && get_number_of_permutations() == 0 &&
1094 single_value.n_elements == recof_value->size_of()) {
1095 size_t previous_size = TTCN_Logger::get_logmatch_buffer_len();
1096 for (int elem_count = 0; elem_count < single_value.n_elements; elem_count++) {
1097 if(!single_value.value_elements[elem_count]->matchv(recof_value->get_at(elem_count), legacy)){
1098 TTCN_Logger::log_logmatch_info("[%d]", elem_count);
1099 single_value.value_elements[elem_count]->log_matchv(recof_value->get_at(elem_count), legacy);
1100 TTCN_Logger::set_logmatch_buffer_len(previous_size);
1101 }
1102 }
1103 log_match_length(single_value.n_elements);
1104 } else {
1105 TTCN_Logger::print_logmatch_buffer();
1106 match_value->log();
1107 TTCN_Logger::log_event_str(" with ");
1108 log();
1109 TTCN_Logger::log_event_str(" unmatched");
1110 }
1111 }
1112 } else {
1113 const Record_Of_Type* recof_value = static_cast<const Record_Of_Type*>(match_value);
1114 if (template_selection == SPECIFIC_VALUE &&
1115 single_value.n_elements > 0 && get_number_of_permutations() == 0 &&
1116 single_value.n_elements == recof_value->size_of()) {
1117 TTCN_Logger::log_event_str("{ ");
1118 for (int elem_count = 0; elem_count < single_value.n_elements; elem_count++) {
1119 if (elem_count > 0) TTCN_Logger::log_event_str(", ");
1120 single_value.value_elements[elem_count]->log_matchv(recof_value->get_at(elem_count), legacy);
1121 }
1122 TTCN_Logger::log_event_str(" }");
1123 log_match_length(single_value.n_elements);
1124 } else {
1125 match_value->log();
1126 TTCN_Logger::log_event_str(" with ");
1127 log();
1128 if (matchv(match_value, legacy)) TTCN_Logger::log_event_str(" matched");
1129 else TTCN_Logger::log_event_str(" unmatched");
1130 }
1131 }
1132 }
1133
1134 void Record_Of_Template::encode_text(Text_Buf& text_buf) const
1135 {
1136 encode_text_permutation(text_buf);
1137 switch (template_selection) {
1138 case SPECIFIC_VALUE:
1139 text_buf.push_int(single_value.n_elements);
1140 for (int elem_count = 0; elem_count < single_value.n_elements; elem_count++)
1141 single_value.value_elements[elem_count]->encode_text(text_buf);
1142 break;
1143 case OMIT_VALUE:
1144 case ANY_VALUE:
1145 case ANY_OR_OMIT:
1146 break;
1147 case VALUE_LIST:
1148 case COMPLEMENTED_LIST:
1149 text_buf.push_int(value_list.n_values);
1150 for (int list_count = 0; list_count < value_list.n_values; list_count++)
1151 value_list.list_value[list_count]->encode_text(text_buf);
1152 break;
1153 default:
1154 TTCN_error("Text encoder: Encoding an uninitialized/unsupported template "
1155 "of type %s.", get_descriptor()->name);
1156 }
1157 }
1158
1159 void Record_Of_Template::decode_text(Text_Buf& text_buf)
1160 {
1161 clean_up();
1162 decode_text_permutation(text_buf);
1163 switch (template_selection) {
1164 case SPECIFIC_VALUE:
1165 single_value.n_elements = text_buf.pull_int().get_val();
1166 if (single_value.n_elements < 0)
1167 TTCN_error("Text decoder: Negative size was received for a template of "
1168 "type %s.", get_descriptor()->name);
1169 single_value.value_elements = (Base_Template**)allocate_pointers(single_value.n_elements);
1170 for (int elem_count = 0; elem_count < single_value.n_elements; elem_count++) {
1171 single_value.value_elements[elem_count] = create_elem();
1172 single_value.value_elements[elem_count]->decode_text(text_buf);
1173 }
1174 break;
1175 case OMIT_VALUE:
1176 case ANY_VALUE:
1177 case ANY_OR_OMIT:
1178 break;
1179 case VALUE_LIST:
1180 case COMPLEMENTED_LIST:
1181 value_list.n_values = text_buf.pull_int().get_val();
1182 value_list.list_value = (Record_Of_Template**)allocate_pointers(value_list.n_values);
1183 for (int list_count = 0; list_count < value_list.n_values; list_count++) {
1184 value_list.list_value[list_count] = create();
1185 value_list.list_value[list_count]->decode_text(text_buf);
1186 }
1187 break;
1188 default:
1189 TTCN_error("Text decoder: An unknown/unsupported selection was received "
1190 "for a template of type %s.", get_descriptor()->name);
1191 }
1192 }
1193
1194 boolean Record_Of_Template::is_present(boolean legacy /* = FALSE */) const
1195 {
1196 if (template_selection==UNINITIALIZED_TEMPLATE) return FALSE;
1197 return !match_omit(legacy);
1198 }
1199
1200 boolean Record_Of_Template::match_omit(boolean legacy /* = FALSE */) const
1201 {
1202 if (is_ifpresent) return TRUE;
1203 switch (template_selection) {
1204 case OMIT_VALUE:
1205 case ANY_OR_OMIT:
1206 return TRUE;
1207 case VALUE_LIST:
1208 case COMPLEMENTED_LIST:
1209 if (legacy) {
1210 // legacy behavior: 'omit' can appear in the value/complement list
1211 for (int i=0; i<value_list.n_values; i++)
1212 if (value_list.list_value[i]->match_omit())
1213 return template_selection==VALUE_LIST;
1214 return template_selection==COMPLEMENTED_LIST;
1215 }
1216 // else fall through
1217 default:
1218 return FALSE;
1219 }
1220 return FALSE;
1221 }
1222
1223 void Record_Of_Template::set_param(Module_Param& param)
1224 {
1225 if (dynamic_cast<Module_Param_Name*>(param.get_id()) != NULL &&
1226 param.get_id()->next_name()) {
1227 // Haven't reached the end of the module parameter name
1228 // => the name refers to one of the elements, not to the whole record of
1229 char* param_field = param.get_id()->get_current_name();
1230 if (param_field[0] < '0' || param_field[0] > '9') {
1231 param.error("Unexpected record field name in module parameter, expected a valid"
1232 " index for record of template type `%s'", get_descriptor()->name);
1233 }
1234 int param_index = -1;
1235 sscanf(param_field, "%d", &param_index);
1236 get_at(param_index)->set_param(param);
1237 return;
1238 }
1239
1240 param.basic_check(Module_Param::BC_TEMPLATE|Module_Param::BC_LIST, "record of template");
1241
1242 Module_Param_Ptr mp = &param;
1243 if (param.get_type() == Module_Param::MP_Reference) {
1244 mp = param.get_referenced_param();
1245 }
1246
1247 switch (mp->get_type()) {
1248 case Module_Param::MP_Omit:
1249 set_value(OMIT_VALUE);
1250 break;
1251 case Module_Param::MP_Any:
1252 set_value(ANY_VALUE);
1253 break;
1254 case Module_Param::MP_AnyOrNone:
1255 set_value(ANY_OR_OMIT);
1256 break;
1257 case Module_Param::MP_List_Template:
1258 case Module_Param::MP_ComplementList_Template: {
1259 Record_Of_Template** list_items = (Record_Of_Template**)
1260 allocate_pointers(mp->get_size());
1261 for (size_t i = 0; i < mp->get_size(); i++) {
1262 list_items[i] = create();
1263 list_items[i]->set_param(*mp->get_elem(i));
1264 }
1265 clean_up();
1266 template_selection = mp->get_type() == Module_Param::MP_List_Template ?
1267 VALUE_LIST : COMPLEMENTED_LIST;
1268 value_list.n_values = mp->get_size();
1269 value_list.list_value = list_items;
1270 break; }
1271 case Module_Param::MP_Value_List: {
1272 set_size(mp->get_size()); // at least this size if there are no permutation elements, if there are then get_at() will automatically resize
1273 int curr_idx = 0; // current index into this
1274 for (size_t i=0; i<mp->get_size(); ++i) {
1275 Module_Param* const curr = mp->get_elem(i);
1276 switch (curr->get_type()) {
1277 case Module_Param::MP_NotUsed:
1278 // skip this element
1279 curr_idx++;
1280 break;
1281 case Module_Param::MP_Permutation_Template: {
1282 // insert all elements from the permutation
1283 int perm_start_idx = curr_idx;
1284 for (size_t perm_i=0; perm_i<curr->get_size(); perm_i++) {
1285 get_at(curr_idx)->set_param(*(curr->get_elem(perm_i)));
1286 curr_idx++;
1287 }
1288 int perm_end_idx = curr_idx - 1;
1289 add_permutation(perm_start_idx, perm_end_idx);
1290 } break;
1291 default:
1292 get_at(curr_idx)->set_param(*curr);
1293 curr_idx++;
1294 }
1295 }
1296 } break;
1297 case Module_Param::MP_Indexed_List:
1298 if (template_selection!=SPECIFIC_VALUE) set_size(0);
1299 for (size_t i=0; i<mp->get_size(); ++i) {
1300 Module_Param* const current = mp->get_elem(i);
1301 get_at((int)current->get_id()->get_index())->set_param(*current);
1302 }
1303 break;
1304 default:
1305 param.type_error("record of template", get_descriptor()->name);
1306 }
1307 is_ifpresent = param.get_ifpresent() || mp->get_ifpresent();
1308 if (param.get_length_restriction() != NULL) {
1309 set_length_range(param);
1310 }
1311 else {
1312 set_length_range(*mp);
1313 }
1314 }
1315
1316 Module_Param* Record_Of_Template::get_param(Module_Param_Name& param_name) const
1317 {
1318 if (param_name.next_name()) {
1319 // Haven't reached the end of the module parameter name
1320 // => the name refers to one of the elements, not to the whole record of
1321 char* param_field = param_name.get_current_name();
1322 if (param_field[0] < '0' || param_field[0] > '9') {
1323 TTCN_error("Unexpected record field name in module parameter reference, "
1324 "expected a valid index for record of template type `%s'",
1325 get_descriptor()->name);
1326 }
1327 int param_index = -1;
1328 sscanf(param_field, "%d", &param_index);
1329 return get_at(param_index)->get_param(param_name);
1330 }
1331 Module_Param* mp = NULL;
1332 switch (template_selection) {
1333 case UNINITIALIZED_TEMPLATE:
1334 mp = new Module_Param_Unbound();
1335 break;
1336 case OMIT_VALUE:
1337 mp = new Module_Param_Omit();
1338 break;
1339 case ANY_VALUE:
1340 mp = new Module_Param_Any();
1341 break;
1342 case ANY_OR_OMIT:
1343 mp = new Module_Param_AnyOrNone();
1344 break;
1345 case SPECIFIC_VALUE: {
1346 Vector<Module_Param*> values;
1347 for (int i = 0; i < single_value.n_elements; ++i) {
1348 values.push_back(single_value.value_elements[i]->get_param(param_name));
1349 }
1350 mp = new Module_Param_Value_List();
1351 mp->add_list_with_implicit_ids(&values);
1352 values.clear();
1353 break; }
1354 case VALUE_LIST:
1355 case COMPLEMENTED_LIST: {
1356 if (template_selection == VALUE_LIST) {
1357 mp = new Module_Param_List_Template();
1358 }
1359 else {
1360 mp = new Module_Param_ComplementList_Template();
1361 }
1362 for (int i = 0; i < value_list.n_values; ++i) {
1363 mp->add_elem(value_list.list_value[i]->get_param(param_name));
1364 }
1365 break; }
1366 default:
1367 break;
1368 }
1369 if (is_ifpresent) {
1370 mp->set_ifpresent();
1371 }
1372 mp->set_length_restriction(get_length_range());
1373 return mp;
1374 }
1375
1376 void Record_Of_Template::check_restriction(template_res t_res, const char* t_name,
1377 boolean legacy /* = FALSE */) const
1378 {
1379 if (template_selection==UNINITIALIZED_TEMPLATE) return;
1380 switch ((t_name && (t_res==TR_VALUE)) ? TR_OMIT : t_res) {
1381 case TR_OMIT:
1382 if (template_selection==OMIT_VALUE) return;
1383 // no break
1384 case TR_VALUE:
1385 if (template_selection!=SPECIFIC_VALUE || is_ifpresent) break;
1386 for (int i=0; i<single_value.n_elements; i++)
1387 single_value.value_elements[i]->check_restriction(t_res, t_name ? t_name : get_descriptor()->name);
1388 return;
1389 case TR_PRESENT:
1390 if (!match_omit(legacy)) return;
1391 break;
1392 default:
1393 return;
1394 }
1395 TTCN_error("Restriction `%s' on template of type %s violated.",
1396 get_res_name(t_res), t_name ? t_name : get_descriptor()->name);
1397 }
1398
1399 ////////////////////////////////////////////////////////////////////////////////
1400
1401 void Set_Of_Template::substr_(int index, int returncount, Record_Of_Type* rec_of) const
1402 {
1403 if (!is_value()) TTCN_error("The first argument of function substr() is a template of type %s with non-specific value.", get_descriptor()->name);
1404 rec_of->set_val(NULL_VALUE);
1405 Base_Type* this_value = rec_of->clone();
1406 valueofv(this_value);
1407 static_cast<Record_Of_Type*>(this_value)->substr_(index, returncount, rec_of);
1408 delete this_value;
1409 }
1410
1411 void Set_Of_Template::replace_(int index, int len,
1412 const Set_Of_Template* repl, Record_Of_Type* rec_of) const
1413 {
1414 if (!is_value()) TTCN_error("The first argument of function replace() is a template of type %s with non-specific value.", get_descriptor()->name);
1415 if (!repl->is_value()) TTCN_error("The fourth argument of function replace() is a template of type %s with non-specific value.", repl->get_descriptor()->name);
1416 rec_of->set_val(NULL_VALUE);
1417 Base_Type* this_value = rec_of->clone();
1418 valueofv(this_value);
1419 Base_Type* repl_value = rec_of->clone();
1420 repl->valueofv(repl_value);
1421 // call the replace() function of the value class instance
1422 static_cast<Record_Of_Type*>(this_value)->replace_(index, len, static_cast<Record_Of_Type*>(repl_value), rec_of);
1423 delete this_value;
1424 delete repl_value;
1425 }
1426
1427 void Set_Of_Template::replace_(int index, int len,
1428 const Record_Of_Type* repl, Record_Of_Type* rec_of) const
1429 {
1430 if (!is_value()) TTCN_error("The first argument of function replace() is a template of type %s with non-specific value.", get_descriptor()->name);
1431 rec_of->set_val(NULL_VALUE);
1432 Base_Type* this_value = rec_of->clone();
1433 valueofv(this_value);
1434 // call the replace() function of the value class instance
1435 static_cast<Record_Of_Type*>(this_value)->replace_(index, len, repl, rec_of);
1436 delete this_value;
1437 }
1438
1439 Set_Of_Template::Set_Of_Template(): err_descr(NULL)
1440 {
1441 }
1442
1443 Set_Of_Template::Set_Of_Template(template_sel other_value)
1444 : Restricted_Length_Template(other_value), err_descr(NULL)
1445 {
1446 }
1447
1448 Set_Of_Template::~Set_Of_Template()
1449 {
1450 clean_up();
1451 }
1452
1453 void Set_Of_Template::clean_up()
1454 {
1455 switch (template_selection) {
1456 case SPECIFIC_VALUE:
1457 case SUPERSET_MATCH:
1458 case SUBSET_MATCH:
1459 for (int elem_count = 0; elem_count < single_value.n_elements; elem_count++)
1460 delete single_value.value_elements[elem_count];
1461 free_pointers((void**)single_value.value_elements);
1462 break;
1463 case VALUE_LIST:
1464 case COMPLEMENTED_LIST:
1465 for (int elem_count = 0; elem_count < value_list.n_values; elem_count++)
1466 delete value_list.list_value[elem_count];
1467 free_pointers((void**)value_list.list_value);
1468 break;
1469 default:
1470 break;
1471 }
1472 template_selection = UNINITIALIZED_TEMPLATE;
1473 }
1474
1475 void Set_Of_Template::copy_value(const Base_Type* other_value)
1476 {
1477 if (!other_value->is_bound())
1478 TTCN_error("Initialization of a set of template with an unbound value.");
1479 const Record_Of_Type* other_setof = static_cast<const Record_Of_Type*>(other_value);
1480 single_value.n_elements = other_setof->size_of();
1481 single_value.value_elements = (Base_Template**)allocate_pointers(single_value.n_elements);
1482 for (int elem_count = 0; elem_count < single_value.n_elements; elem_count++) {
1483 single_value.value_elements[elem_count] = create_elem();
1484 single_value.value_elements[elem_count]->copy_value(other_setof->get_at(elem_count));
1485 }
1486 set_selection(SPECIFIC_VALUE);
1487 err_descr = other_setof->get_err_descr();
1488 }
1489
1490 void Set_Of_Template::copy_optional(const Base_Type* other_value)
1491 {
1492 if (other_value->is_present()) {
1493 const Record_Of_Type* other_setof = static_cast<const Record_Of_Type*>(other_value->get_opt_value());
1494 copy_value(other_setof);
1495 } else if (other_value->is_bound()) {
1496 set_selection(OMIT_VALUE);
1497 err_descr = NULL;
1498 } else {
1499 TTCN_error("Initialization of a set of template with an unbound optional field.");
1500 }
1501 }
1502
1503 void Set_Of_Template::copy_template(const Set_Of_Template& other_value)
1504 {
1505 switch (other_value.template_selection) {
1506 case SPECIFIC_VALUE:
1507 case SUPERSET_MATCH:
1508 case SUBSET_MATCH:
1509 single_value.n_elements = other_value.single_value.n_elements;
1510 single_value.value_elements = (Base_Template**)allocate_pointers(single_value.n_elements);
1511 for (int elem_count = 0; elem_count < single_value.n_elements; elem_count++)
1512 single_value.value_elements[elem_count] = other_value.single_value.value_elements[elem_count]->clone();
1513 break;
1514 case OMIT_VALUE:
1515 case ANY_VALUE:
1516 case ANY_OR_OMIT:
1517 break;
1518 case VALUE_LIST:
1519 case COMPLEMENTED_LIST:
1520 value_list.n_values = other_value.value_list.n_values;
1521 value_list.list_value = (Set_Of_Template**)allocate_pointers(value_list.n_values);
1522 for (int list_count = 0; list_count < value_list.n_values; list_count++)
1523 value_list.list_value[list_count] = static_cast<Set_Of_Template*>(other_value.value_list.list_value[list_count]->clone());
1524 break;
1525 default:
1526 TTCN_error("Copying an uninitialized/unsupported set of template");
1527 break;
1528 }
1529 set_selection(other_value);
1530 err_descr = other_value.err_descr;
1531 }
1532
1533 Base_Template* Set_Of_Template::clone() const
1534 {
1535 Set_Of_Template* setof = create();
1536 setof->copy_template(*this);
1537 return setof;
1538 }
1539
1540 Base_Template* Set_Of_Template::get_at(int index_value)
1541 {
1542 if (index_value < 0)
1543 TTCN_error("Accessing an element of a template for type %s using a "
1544 "negative index: %d.", get_descriptor()->name, index_value);
1545 if (template_selection != SPECIFIC_VALUE ||
1546 index_value >= single_value.n_elements) set_size(index_value + 1);
1547 return single_value.value_elements[index_value];
1548 }
1549
1550 Base_Template* Set_Of_Template::get_at(const INTEGER& index_value)
1551 {
1552 if (!index_value.is_bound())
1553 TTCN_error("Using an unbound integer value for indexing a template of "
1554 "type %s.", get_descriptor()->name);
1555 return get_at((int)index_value);
1556 }
1557
1558 const Base_Template* Set_Of_Template::get_at(int index_value) const
1559 {
1560 if (index_value < 0)
1561 TTCN_error("Accessing an element of a template for type %s using "
1562 "a negative index: %d.", get_descriptor()->name, index_value);
1563 if (template_selection != SPECIFIC_VALUE)
1564 TTCN_error("Accessing an element of a non-specific template for type %s.",
1565 get_descriptor()->name);
1566 if (index_value >= single_value.n_elements)
1567 TTCN_error("Index overflow in a template of type %s: The index is %d, but "
1568 "the template has only %d elements.", get_descriptor()->name,
1569 index_value, single_value.n_elements);
1570 return single_value.value_elements[index_value];
1571 }
1572
1573 const Base_Template* Set_Of_Template::get_at(const INTEGER& index_value) const
1574 {
1575 if (!index_value.is_bound())
1576 TTCN_error("Using an unbound integer value for indexing a template of "
1577 "type %s.", get_descriptor()->name);
1578 return get_at((int)index_value);
1579 }
1580
1581 void Set_Of_Template::set_size(int new_size)
1582 {
1583 if (new_size < 0)
1584 TTCN_error("Internal error: Setting a negative size for a template of "
1585 "type %s.", get_descriptor()->name);
1586 template_sel old_selection = template_selection;
1587 if (old_selection != SPECIFIC_VALUE) {
1588 clean_up();
1589 set_selection(SPECIFIC_VALUE);
1590 single_value.n_elements = 0;
1591 single_value.value_elements = NULL;
1592 }
1593 if (new_size > single_value.n_elements) {
1594 single_value.value_elements = (Base_Template**)reallocate_pointers((void**)
1595 single_value.value_elements, single_value.n_elements, new_size);
1596 if (old_selection == ANY_VALUE || old_selection == ANY_OR_OMIT) {
1597 for (int elem_count = single_value.n_elements;
1598 elem_count < new_size; elem_count++) {
1599 single_value.value_elements[elem_count] = create_elem();
1600 single_value.value_elements[elem_count]->set_value(ANY_VALUE);
1601 }
1602 } else {
1603 for (int elem_count = single_value.n_elements;
1604 elem_count < new_size; elem_count++)
1605 single_value.value_elements[elem_count] = create_elem();
1606 }
1607 single_value.n_elements = new_size;
1608 } else if (new_size < single_value.n_elements) {
1609 for (int elem_count = new_size;
1610 elem_count < single_value.n_elements; elem_count++)
1611 delete single_value.value_elements[elem_count];
1612 single_value.value_elements = (Base_Template**)reallocate_pointers((void**)
1613 single_value.value_elements, single_value.n_elements, new_size);
1614 single_value.n_elements = new_size;
1615 }
1616 }
1617
1618 int Set_Of_Template::size_of(boolean is_size) const
1619 {
1620 const char* op_name = is_size ? "size" : "length";
1621 int min_size = -1;
1622 boolean has_any_or_none = FALSE;
1623 if (is_ifpresent)
1624 TTCN_error("Performing %sof() operation on a template of type %s "
1625 "which has an ifpresent attribute.", op_name, get_descriptor()->name);
1626 switch (template_selection)
1627 {
1628 case SPECIFIC_VALUE:
1629 case SUPERSET_MATCH:
1630 case SUBSET_MATCH: {
1631 min_size = 0;
1632 has_any_or_none = FALSE;
1633 int elem_count = single_value.n_elements;
1634 if (!is_size) {
1635 while (elem_count>0 && !single_value.value_elements[elem_count-1]->is_bound())
1636 elem_count--;
1637 }
1638 for (int i=0; i<elem_count; i++)
1639 {
1640 switch (single_value.value_elements[i]->get_selection())
1641 {
1642 case OMIT_VALUE:
1643 TTCN_error("Performing %sof() operation on a template of type %s "
1644 "containing omit element.", op_name, get_descriptor()->name);
1645 case ANY_OR_OMIT:
1646 has_any_or_none = TRUE;
1647 break;
1648 default:
1649 min_size++;
1650 break;
1651 }
1652 }
1653 if (template_selection==SUPERSET_MATCH)
1654 {
1655 has_any_or_none = TRUE;
1656 }
1657 else if (template_selection==SUBSET_MATCH)
1658 {
1659 int max_size = min_size;
1660 min_size = 0;
1661 if (!has_any_or_none) // [0,max_size]
1662 {
1663 switch (length_restriction_type)
1664 {
1665 case NO_LENGTH_RESTRICTION:
1666 if (max_size==0) return 0;
1667 TTCN_error("Performing %sof() operation on a template of type "
1668 "%s with no exact size.", op_name, get_descriptor()->name);
1669 case SINGLE_LENGTH_RESTRICTION:
1670 if (length_restriction.single_length<=max_size)
1671 return length_restriction.single_length;
1672 TTCN_error("Performing %sof() operation on an invalid template of "
1673 "type %s. The maximum size (%d) contradicts the length restriction "
1674 "(%d).", op_name, get_descriptor()->name, max_size,
1675 length_restriction.single_length);
1676 case RANGE_LENGTH_RESTRICTION:
1677 if (max_size==length_restriction.range_length.min_length)
1678 return max_size;
1679 else if (max_size>length_restriction.range_length.min_length)
1680 TTCN_error("Performing %sof() operation on a template of type %s "
1681 "with no exact size.", op_name, get_descriptor()->name);
1682 else
1683 TTCN_error("Performing %sof() operation on an invalid template of "
1684 "type %s. Maximum size (%d) contradicts the length restriction "
1685 "(%d..%d).", op_name, get_descriptor()->name, max_size,
1686 length_restriction.range_length.min_length,
1687 length_restriction.range_length.max_length);
1688 default:
1689 TTCN_error("Internal error: Template has invalid length restriction type.");
1690 }
1691 }
1692 }
1693 } break;
1694 case OMIT_VALUE:
1695 TTCN_error("Performing %sof() operation on a template of type %s"
1696 " containing omit value.", op_name, get_descriptor()->name);
1697 case ANY_VALUE:
1698 case ANY_OR_OMIT:
1699 min_size = 0;
1700 has_any_or_none = TRUE;
1701 break;
1702 case VALUE_LIST:
1703 {
1704 if (value_list.n_values<1)
1705 TTCN_error("Performing %sof() operation on a template of type %s "
1706 "containing an empty list.", op_name, get_descriptor()->name);
1707 int item_size = value_list.list_value[0]->size_of(is_size);
1708 for (int i = 1; i < value_list.n_values; i++) {
1709 if (value_list.list_value[i]->size_of(is_size)!=item_size)
1710 TTCN_error("Performing %sof() operation on a template of type %s "
1711 "containing a value list with different sizes.", op_name, get_descriptor()->name);
1712 }
1713 min_size = item_size;
1714 has_any_or_none = FALSE;
1715 break;
1716 }
1717 case COMPLEMENTED_LIST:
1718 TTCN_error("Performing %sof() operation on a template of type %s "
1719 "containing complemented list.", op_name, get_descriptor()->name);
1720 case UNINITIALIZED_TEMPLATE:
1721 case VALUE_RANGE:
1722 case STRING_PATTERN:
1723 case DECODE_MATCH:
1724 TTCN_error("Performing %sof() operation on an uninitialized/unsupported "
1725 "template of type %s.", op_name, get_descriptor()->name);
1726 }
1727 return check_section_is_single(min_size, has_any_or_none, op_name,
1728 "a template of type", get_descriptor()->name);
1729 }
1730
1731 int Set_Of_Template::n_elem() const
1732 {
1733 switch (template_selection) {
1734 case SPECIFIC_VALUE:
1735 case SUPERSET_MATCH:
1736 case SUBSET_MATCH:
1737 return single_value.n_elements;
1738
1739 case COMPLEMENTED_LIST:
1740 TTCN_error("Performing n_elem() operation on a template of type %s "
1741 "containing complemented list.", get_descriptor()->name);
1742
1743 case UNINITIALIZED_TEMPLATE:
1744 case OMIT_VALUE:
1745 case ANY_VALUE:
1746 case ANY_OR_OMIT:
1747 case VALUE_LIST:
1748 case VALUE_RANGE:
1749 case STRING_PATTERN:
1750 case DECODE_MATCH:
1751 break;
1752 }
1753 TTCN_error("Performing n_elem() operation on an uninitialized/unsupported "
1754 "template of type %s.", get_descriptor()->name);
1755 }
1756
1757 boolean Set_Of_Template::match_function_specific(
1758 const Base_Type *value_ptr, int value_index,
1759 const Restricted_Length_Template *template_ptr, int template_index,
1760 boolean legacy)
1761 {
1762 const Set_Of_Template* set_tmpl_ptr = static_cast<const Set_Of_Template*>(template_ptr);
1763 if (value_index >= 0) {
1764 const Record_Of_Type* recof_ptr = static_cast<const Record_Of_Type*>(value_ptr);
1765 return set_tmpl_ptr->single_value.value_elements[template_index]->matchv(recof_ptr->get_at(value_index), legacy);
1766 } else {
1767 return set_tmpl_ptr->single_value.value_elements[template_index]->is_any_or_omit();
1768 }
1769 }
1770
1771 boolean Set_Of_Template::match_function_set(
1772 const Base_Type *value_ptr, int value_index,
1773 const Restricted_Length_Template *template_ptr, int template_index,
1774 boolean legacy)
1775 {
1776 const Set_Of_Template* set_tmpl_ptr = static_cast<const Set_Of_Template*>(template_ptr);
1777 if (value_index >= 0) {
1778 const Record_Of_Type* recof_ptr = static_cast<const Record_Of_Type*>(value_ptr);
1779 return set_tmpl_ptr->single_value.value_elements[template_index]->matchv(recof_ptr->get_at(value_index), legacy);
1780 } else {
1781 return set_tmpl_ptr->single_value.value_elements[template_index]->is_any_or_omit();
1782 }
1783 }
1784
1785 void Set_Of_Template::log_function(
1786 const Base_Type *value_ptr, const Restricted_Length_Template *template_ptr,
1787 int index_value, int index_template, boolean legacy)
1788 {
1789 const Set_Of_Template* set_tmpl_ptr = static_cast<const Set_Of_Template*>(template_ptr);
1790 const Record_Of_Type* recof_ptr = static_cast<const Record_Of_Type*>(value_ptr);
1791 if (value_ptr != NULL && template_ptr != NULL)
1792 set_tmpl_ptr->single_value.value_elements[index_template]->log_matchv(recof_ptr->get_at(index_value), legacy);
1793 else if (value_ptr != NULL)
1794 recof_ptr->get_at(index_value)->log();
1795 else if (template_ptr != NULL)
1796 set_tmpl_ptr->single_value.value_elements[index_template]->log();
1797 }
1798
1799 boolean Set_Of_Template::matchv(const Base_Type* other_value,
1800 boolean legacy) const
1801 {
1802 const Record_Of_Type* other_recof = static_cast<const Record_Of_Type*>(other_value);
1803 if (!other_recof->is_bound())
1804 TTCN_error("Matching an unbound value of type %s with a template.",
1805 other_recof->get_descriptor()->name);
1806 int value_length = other_recof->size_of();
1807 if (!match_length(value_length)) return FALSE;
1808 switch (template_selection) {
1809 case SPECIFIC_VALUE:
1810 return match_set_of(other_recof, value_length, this,
1811 single_value.n_elements, match_function_specific, legacy);
1812 case OMIT_VALUE:
1813 return FALSE;
1814 case ANY_VALUE:
1815 case ANY_OR_OMIT:
1816 return TRUE;
1817 case VALUE_LIST:
1818 case COMPLEMENTED_LIST:
1819 for (int list_count = 0; list_count < value_list.n_values; list_count++)
1820 if (value_list.list_value[list_count]->matchv(other_recof, legacy))
1821 return template_selection == VALUE_LIST;
1822 return template_selection == COMPLEMENTED_LIST;
1823 case SUPERSET_MATCH:
1824 case SUBSET_MATCH:
1825 return match_set_of(other_recof, value_length, this,
1826 single_value.n_elements, match_function_set, legacy);
1827 default:
1828 TTCN_error("Matching with an uninitialized/unsupported template of type %s.",
1829 get_descriptor()->name);
1830 }
1831 return FALSE;
1832 }
1833
1834 boolean Set_Of_Template::is_value() const
1835 {
1836 if (template_selection != SPECIFIC_VALUE || is_ifpresent) return FALSE;
1837 for (int elem_count = 0; elem_count < single_value.n_elements; elem_count++)
1838 if (!single_value.value_elements[elem_count]->is_value()) return FALSE;
1839 return TRUE;
1840 }
1841
1842 void Set_Of_Template::valueofv(Base_Type* value) const
1843 {
1844 if (template_selection != SPECIFIC_VALUE || is_ifpresent)
1845 TTCN_error("Performing a valueof or send operation on a non-specific template of type %s.", get_descriptor()->name);
1846 Record_Of_Type* setof_value = static_cast<Record_Of_Type*>(value);
1847 setof_value->set_size(single_value.n_elements);
1848 for (int elem_count = 0; elem_count < single_value.n_elements; elem_count++)
1849 single_value.value_elements[elem_count]->valueofv(setof_value->get_at(elem_count));
1850 setof_value->set_err_descr(err_descr);
1851 }
1852
1853 void Set_Of_Template::set_value(template_sel other_value)
1854 {
1855 check_single_selection(other_value);
1856 clean_up();
1857 set_selection(other_value);
1858 err_descr = NULL;
1859 }
1860
1861 void Set_Of_Template::set_type(template_sel template_type, int list_length)
1862 {
1863 clean_up();
1864 switch (template_type) {
1865 case VALUE_LIST:
1866 case COMPLEMENTED_LIST:
1867 value_list.n_values = list_length;
1868 value_list.list_value = (Set_Of_Template**)allocate_pointers(value_list.n_values);
1869 for (int list_count = 0; list_count < value_list.n_values; list_count++)
1870 value_list.list_value[list_count] = create();
1871 break;
1872 case SUPERSET_MATCH:
1873 case SUBSET_MATCH:
1874 single_value.n_elements = list_length;
1875 single_value.value_elements = (Base_Template**)allocate_pointers(single_value.n_elements);
1876 for (int set_count = 0; set_count < single_value.n_elements; set_count++)
1877 single_value.value_elements[set_count] = create_elem();
1878 break;
1879 default:
1880 TTCN_error("Internal error: Setting an invalid type for a template of "
1881 "type %s.", get_descriptor()->name);
1882 }
1883 set_selection(template_type);
1884 }
1885
1886 Set_Of_Template* Set_Of_Template::get_list_item(int list_index)
1887 {
1888 if (template_selection != VALUE_LIST && template_selection != COMPLEMENTED_LIST)
1889 TTCN_error("Internal error: Accessing a list element of a non-list "
1890 "template of type %s.", get_descriptor()->name);
1891 if (list_index >= value_list.n_values || list_index < 0)
1892 TTCN_error("Internal error: Index overflow in a value list template "
1893 "of type %s.", get_descriptor()->name);
1894 return value_list.list_value[list_index];
1895 }
1896
1897 Base_Template* Set_Of_Template::get_set_item(int set_index)
1898 {
1899 if (template_selection != SUPERSET_MATCH && template_selection != SUBSET_MATCH)
1900 TTCN_error("Internal error: Accessing a set element of a non-set "
1901 "template of type %s.", get_descriptor()->name);
1902 if (set_index >= single_value.n_elements || set_index < 0)
1903 TTCN_error("Internal error: Index overflow in a set template of "
1904 "type %s.", get_descriptor()->name);
1905 return single_value.value_elements[set_index];
1906 }
1907
1908 void Set_Of_Template::log() const
1909 {
1910 switch (template_selection) {
1911 case SPECIFIC_VALUE:
1912 if (single_value.n_elements > 0) {
1913 TTCN_Logger::log_event_str("{ ");
1914 for (int elem_count = 0; elem_count < single_value.n_elements; elem_count++) {
1915 if (elem_count > 0) TTCN_Logger::log_event_str(", ");
1916 single_value.value_elements[elem_count]->log();
1917 }
1918 TTCN_Logger::log_event_str(" }");
1919 } else TTCN_Logger::log_event_str("{ }");
1920 break;
1921 case COMPLEMENTED_LIST:
1922 TTCN_Logger::log_event_str("complement ");
1923 // no break
1924 case VALUE_LIST:
1925 TTCN_Logger::log_char('(');
1926 for (int list_count = 0; list_count < value_list.n_values; list_count++) {
1927 if (list_count > 0) TTCN_Logger::log_event_str(", ");
1928 value_list.list_value[list_count]->log();
1929 }
1930 TTCN_Logger::log_char(')');
1931 break;
1932 case SUPERSET_MATCH:
1933 case SUBSET_MATCH:
1934 TTCN_Logger::log_event("%s(",
1935 template_selection == SUPERSET_MATCH ? "superset" : "subset");
1936 for (int set_count = 0; set_count < single_value.n_elements; set_count++) {
1937 if (set_count > 0) TTCN_Logger::log_event_str(", ");
1938 single_value.value_elements[set_count]->log();
1939 }
1940 TTCN_Logger::log_char(')');
1941 break;
1942 default:
1943 log_generic();
1944 break;
1945 }
1946 log_restricted();
1947 log_ifpresent();
1948 if (err_descr) err_descr->log();
1949 }
1950
1951 void Set_Of_Template::log_matchv(const Base_Type* match_value, boolean legacy) const
1952 {
1953 if (TTCN_Logger::VERBOSITY_COMPACT == TTCN_Logger::get_matching_verbosity()) {
1954 if (matchv(match_value, legacy)) {
1955 TTCN_Logger::print_logmatch_buffer();
1956 TTCN_Logger::log_event_str(" matched");
1957 } else {
1958 size_t previous_size = TTCN_Logger::get_logmatch_buffer_len();
1959 if (template_selection == SPECIFIC_VALUE) {
1960 const Record_Of_Type* setof_value = static_cast<const Record_Of_Type*>(match_value);
1961 log_match_heuristics(setof_value, setof_value->size_of(), this,
1962 single_value.n_elements, match_function_specific, log_function, legacy);
1963 } else {
1964 if (previous_size != 0) {
1965 TTCN_Logger::print_logmatch_buffer();
1966 TTCN_Logger::set_logmatch_buffer_len(previous_size);
1967 TTCN_Logger::log_event_str(":=");
1968 }
1969 match_value->log();
1970 TTCN_Logger::log_event_str(" with ");
1971 log();
1972 TTCN_Logger::log_event_str(" unmatched");
1973 }
1974 }
1975 } else {
1976 match_value->log();
1977 TTCN_Logger::log_event_str(" with ");
1978 log();
1979 if (matchv(match_value, legacy)) TTCN_Logger::log_event_str(" matched");
1980 else {
1981 TTCN_Logger::log_event_str(" unmatched");
1982 if (template_selection == SPECIFIC_VALUE) {
1983 const Record_Of_Type* setof_value = static_cast<const Record_Of_Type*>(match_value);
1984 log_match_heuristics(setof_value, setof_value->size_of(), this,
1985 single_value.n_elements, match_function_specific, log_function, legacy);
1986 }
1987 }
1988 }
1989 }
1990
1991 void Set_Of_Template::encode_text(Text_Buf& text_buf) const
1992 {
1993 encode_text_restricted(text_buf);
1994 switch (template_selection) {
1995 case SPECIFIC_VALUE:
1996 case SUPERSET_MATCH:
1997 case SUBSET_MATCH:
1998 text_buf.push_int(single_value.n_elements);
1999 for (int elem_count = 0; elem_count < single_value.n_elements; elem_count++)
2000 single_value.value_elements[elem_count]->encode_text(text_buf);
2001 break;
2002 case OMIT_VALUE:
2003 case ANY_VALUE:
2004 case ANY_OR_OMIT:
2005 break;
2006 case VALUE_LIST:
2007 case COMPLEMENTED_LIST:
2008 text_buf.push_int(value_list.n_values);
2009 for (int list_count = 0; list_count < value_list.n_values; list_count++)
2010 value_list.list_value[list_count]->encode_text(text_buf);
2011 break;
2012 default:
2013 TTCN_error("Text encoder: Encoding an uninitialized/unsupported template "
2014 "of type %s.", get_descriptor()->name);
2015 }
2016 }
2017
2018 void Set_Of_Template::decode_text(Text_Buf& text_buf)
2019 {
2020 clean_up();
2021 decode_text_restricted(text_buf);
2022 switch (template_selection) {
2023 case SPECIFIC_VALUE:
2024 case SUPERSET_MATCH:
2025 case SUBSET_MATCH:
2026 single_value.n_elements = text_buf.pull_int().get_val();
2027 if (single_value.n_elements < 0)
2028 TTCN_error("Text decoder: Negative size was received for a template of "
2029 "type %s.", get_descriptor()->name);
2030 single_value.value_elements = (Base_Template**)allocate_pointers(single_value.n_elements);
2031 for (int elem_count = 0; elem_count < single_value.n_elements; elem_count++) {
2032 single_value.value_elements[elem_count] = create_elem();
2033 single_value.value_elements[elem_count]->decode_text(text_buf);
2034 }
2035 break;
2036 case OMIT_VALUE:
2037 case ANY_VALUE:
2038 case ANY_OR_OMIT:
2039 break;
2040 case VALUE_LIST:
2041 case COMPLEMENTED_LIST:
2042 value_list.n_values = text_buf.pull_int().get_val();
2043 value_list.list_value = (Set_Of_Template**)allocate_pointers(value_list.n_values);
2044 for (int list_count = 0; list_count < value_list.n_values; list_count++) {
2045 value_list.list_value[list_count] = create();
2046 value_list.list_value[list_count]->decode_text(text_buf);
2047 }
2048 break;
2049 default:
2050 TTCN_error("Text decoder: An unknown/unsupported selection was received "
2051 "for a template of type %s.", get_descriptor()->name);
2052 }
2053 }
2054
2055 boolean Set_Of_Template::is_present(boolean legacy /* = FALSE */) const
2056 {
2057 if (template_selection==UNINITIALIZED_TEMPLATE) return FALSE;
2058 return !match_omit(legacy);
2059 }
2060
2061 boolean Set_Of_Template::match_omit(boolean legacy /* = FALSE */) const
2062 {
2063 if (is_ifpresent) return TRUE;
2064 switch (template_selection) {
2065 case OMIT_VALUE:
2066 case ANY_OR_OMIT:
2067 return TRUE;
2068 case VALUE_LIST:
2069 case COMPLEMENTED_LIST:
2070 if (legacy) {
2071 // legacy behavior: 'omit' can appear in the value/complement list
2072 for (int i=0; i<value_list.n_values; i++)
2073 if (value_list.list_value[i]->match_omit())
2074 return template_selection==VALUE_LIST;
2075 return template_selection==COMPLEMENTED_LIST;
2076 }
2077 // else fall through
2078 default:
2079 return FALSE;
2080 }
2081 return FALSE;
2082 }
2083
2084 void Set_Of_Template::set_param(Module_Param& param)
2085 {
2086 if (dynamic_cast<Module_Param_Name*>(param.get_id()) != NULL &&
2087 param.get_id()->next_name()) {
2088 // Haven't reached the end of the module parameter name
2089 // => the name refers to one of the elements, not to the whole record of
2090 char* param_field = param.get_id()->get_current_name();
2091 if (param_field[0] < '0' || param_field[0] > '9') {
2092 param.error("Unexpected record field name in module parameter, expected a valid"
2093 " index for set of template type `%s'", get_descriptor()->name);
2094 }
2095 int param_index = -1;
2096 sscanf(param_field, "%d", &param_index);
2097 get_at(param_index)->set_param(param);
2098 return;
2099 }
2100
2101 param.basic_check(Module_Param::BC_TEMPLATE|Module_Param::BC_LIST, "set of template");
2102
2103 Module_Param_Ptr mp = &param;
2104 if (param.get_type() == Module_Param::MP_Reference) {
2105 mp = param.get_referenced_param();
2106 }
2107
2108 switch (mp->get_type()) {
2109 case Module_Param::MP_Omit:
2110 set_value(OMIT_VALUE);
2111 break;
2112 case Module_Param::MP_Any:
2113 set_value(ANY_VALUE);
2114 break;
2115 case Module_Param::MP_AnyOrNone:
2116 set_value(ANY_OR_OMIT);
2117 break;
2118 case Module_Param::MP_List_Template:
2119 case Module_Param::MP_ComplementList_Template: {
2120 Set_Of_Template** list_items = (Set_Of_Template**)
2121 allocate_pointers(mp->get_size());
2122 for (size_t i = 0; i < mp->get_size(); i++) {
2123 list_items[i] = create();
2124 list_items[i]->set_param(*mp->get_elem(i));
2125 }
2126 clean_up();
2127 template_selection = mp->get_type() == Module_Param::MP_List_Template ?
2128 VALUE_LIST : COMPLEMENTED_LIST;
2129 value_list.n_values = mp->get_size();
2130 value_list.list_value = list_items;
2131 break; }
2132 case Module_Param::MP_Value_List:
2133 set_size(mp->get_size());
2134 for (size_t i=0; i<mp->get_size(); ++i) {
2135 Module_Param* const curr = mp->get_elem(i);
2136 if (curr->get_type()!=Module_Param::MP_NotUsed) {
2137 get_at(i)->set_param(*curr);
2138 }
2139 }
2140 break;
2141 case Module_Param::MP_Indexed_List:
2142 if (template_selection!=SPECIFIC_VALUE) set_size(0);
2143 for (size_t i=0; i<mp->get_size(); ++i) {
2144 Module_Param* const current = mp->get_elem(i);
2145 get_at((int)current->get_id()->get_index())->set_param(*current);
2146 }
2147 break;
2148 case Module_Param::MP_Superset_Template:
2149 case Module_Param::MP_Subset_Template:
2150 set_type(mp->get_type()==Module_Param::MP_Superset_Template ? SUPERSET_MATCH : SUBSET_MATCH, mp->get_size());
2151 for (size_t i=0; i<mp->get_size(); i++) {
2152 get_set_item((int)i)->set_param(*mp->get_elem(i));
2153 }
2154 break;
2155 default:
2156 param.type_error("set of template", get_descriptor()->name);
2157 }
2158 is_ifpresent = param.get_ifpresent() || mp->get_ifpresent();
2159 if (param.get_length_restriction() != NULL) {
2160 set_length_range(param);
2161 }
2162 else {
2163 set_length_range(*mp);
2164 }
2165 }
2166
2167 Module_Param* Set_Of_Template::get_param(Module_Param_Name& param_name) const
2168 {
2169 if (param_name.next_name()) {
2170 // Haven't reached the end of the module parameter name
2171 // => the name refers to one of the elements, not to the whole record of
2172 char* param_field = param_name.get_current_name();
2173 if (param_field[0] < '0' || param_field[0] > '9') {
2174 TTCN_error("Unexpected record field name in module parameter reference, "
2175 "expected a valid index for set of template type `%s'",
2176 get_descriptor()->name);
2177 }
2178 int param_index = -1;
2179 sscanf(param_field, "%d", &param_index);
2180 return get_at(param_index)->get_param(param_name);
2181 }
2182 Module_Param* mp = NULL;
2183 switch (template_selection) {
2184 case UNINITIALIZED_TEMPLATE:
2185 mp = new Module_Param_Unbound();
2186 break;
2187 case OMIT_VALUE:
2188 mp = new Module_Param_Omit();
2189 break;
2190 case ANY_VALUE:
2191 mp = new Module_Param_Any();
2192 break;
2193 case ANY_OR_OMIT:
2194 mp = new Module_Param_AnyOrNone();
2195 break;
2196 case SPECIFIC_VALUE: {
2197 Vector<Module_Param*> values;
2198 for (int i = 0; i < single_value.n_elements; ++i) {
2199 values.push_back(single_value.value_elements[i]->get_param(param_name));
2200 }
2201 mp = new Module_Param_Value_List();
2202 mp->add_list_with_implicit_ids(&values);
2203 values.clear();
2204 break; }
2205 case VALUE_LIST:
2206 case COMPLEMENTED_LIST: {
2207 if (template_selection == VALUE_LIST) {
2208 mp = new Module_Param_List_Template();
2209 }
2210 else {
2211 mp = new Module_Param_ComplementList_Template();
2212 }
2213 for (int i = 0; i < value_list.n_values; ++i) {
2214 mp->add_elem(value_list.list_value[i]->get_param(param_name));
2215 }
2216 break; }
2217 default:
2218 break;
2219 }
2220 if (is_ifpresent) {
2221 mp->set_ifpresent();
2222 }
2223 mp->set_length_restriction(get_length_range());
2224 return mp;
2225 }
2226
2227 void Set_Of_Template::check_restriction(template_res t_res, const char* t_name,
2228 boolean legacy /* = FALSE */) const
2229 {
2230 if (template_selection==UNINITIALIZED_TEMPLATE) return;
2231 switch ((t_name&&(t_res==TR_VALUE))?TR_OMIT:t_res) {
2232 case TR_OMIT:
2233 if (template_selection==OMIT_VALUE) return;
2234 // no break
2235 case TR_VALUE:
2236 if (template_selection!=SPECIFIC_VALUE || is_ifpresent) break;
2237 for (int i=0; i<single_value.n_elements; i++)
2238 single_value.value_elements[i]->check_restriction(t_res, t_name ? t_name : get_descriptor()->name);
2239 return;
2240 case TR_PRESENT:
2241 if (!match_omit(legacy)) return;
2242 break;
2243 default:
2244 return;
2245 }
2246 TTCN_error("Restriction `%s' on template of type %s violated.",
2247 get_res_name(t_res), t_name ? t_name : get_descriptor()->name);
2248 }
2249
2250 ////////////////////////////////////////////////////////////////////////////////
2251
2252 Record_Template::Record_Template(): Base_Template(), err_descr(NULL)
2253 {
2254 }
2255
2256 Record_Template::Record_Template(template_sel other_value):
2257 Base_Template(other_value), err_descr(NULL)
2258 {
2259 check_single_selection(other_value);
2260 }
2261
2262 Record_Template::~Record_Template()
2263 {
2264 clean_up();
2265 }
2266
2267 void Record_Template::clean_up()
2268 {
2269 switch (template_selection) {
2270 case SPECIFIC_VALUE:
2271 for (int elem_count = 0; elem_count < single_value.n_elements; elem_count++)
2272 delete single_value.value_elements[elem_count];
2273 free_pointers((void**)single_value.value_elements);
2274 break;
2275 case VALUE_LIST:
2276 case COMPLEMENTED_LIST:
2277 for (int elem_count = 0; elem_count < value_list.n_values; elem_count++)
2278 delete value_list.list_value[elem_count];
2279 free_pointers((void**)value_list.list_value);
2280 break;
2281 default:
2282 break;
2283 }
2284 template_selection = UNINITIALIZED_TEMPLATE;
2285 }
2286
2287 void Record_Template::copy_value(const Base_Type* other_value)
2288 {
2289 if (!other_value->is_bound())
2290 TTCN_error("Initialization of a record/set template with an unbound value.");
2291 set_specific();
2292 const Record_Type* other_rec = static_cast<const Record_Type*>(other_value);
2293 const int* optional_indexes = other_rec->get_optional_indexes();
2294 int next_optional_idx = 0;
2295 for (int elem_count = 0; elem_count < single_value.n_elements; elem_count++) {
2296 boolean is_optional = optional_indexes && (optional_indexes[next_optional_idx]==elem_count);
2297 if (is_optional) next_optional_idx++;
2298 const Base_Type* elem_value = other_rec->get_at(elem_count);
2299 if (!elem_value->is_bound()) continue;
2300 if (is_optional) {
2301 if (elem_value->is_present()) {
2302 single_value.value_elements[elem_count]->copy_value(other_rec->get_at(elem_count)->get_opt_value());
2303 } else {
2304 single_value.value_elements[elem_count]->set_value(OMIT_VALUE);
2305 }
2306 } else {
2307 single_value.value_elements[elem_count]->copy_value(other_rec->get_at(elem_count));
2308 }
2309 }
2310 err_descr = other_rec->get_err_descr();
2311 }
2312
2313 void Record_Template::copy_template(const Record_Template& other_value)
2314 {
2315 switch (other_value.template_selection) {
2316 case SPECIFIC_VALUE:
2317 set_specific(); // FIXME: create_elem(int elem_idx) should be used, but that's more code to generate...
2318 // single_value.n_elements = other_value.single_value.n_elements;
2319 // single_value.value_elements = (Base_Template**)allocate_pointers(single_value.n_elements);
2320 for (int elem_count = 0; elem_count < single_value.n_elements; elem_count++) {
2321 if (other_value.single_value.value_elements[elem_count]->is_bound()) {
2322 delete single_value.value_elements[elem_count]; // FIXME: unbound elements should not be created when the element is bound
2323 single_value.value_elements[elem_count] = other_value.single_value.value_elements[elem_count]->clone();
2324 }
2325 }
2326 break;
2327 case OMIT_VALUE:
2328 case ANY_VALUE:
2329 case ANY_OR_OMIT:
2330 break;
2331 case VALUE_LIST:
2332 case COMPLEMENTED_LIST:
2333 value_list.n_values = other_value.value_list.n_values;
2334 value_list.list_value = (Record_Template**)allocate_pointers(value_list.n_values);
2335 for (int list_count = 0; list_count < value_list.n_values; list_count++) {
2336 if (other_value.value_list.list_value[list_count]->is_bound()) {
2337 value_list.list_value[list_count] = static_cast<Record_Template*>(other_value.value_list.list_value[list_count]->clone());
2338 } else {
2339 value_list.list_value[list_count] = create();
2340 }
2341 }
2342 break;
2343 default:
2344 TTCN_error("Copying an uninitialized/unsupported record/set template.");
2345 break;
2346 }
2347 set_selection(other_value);
2348 err_descr = other_value.err_descr;
2349 }
2350
2351 void Record_Template::copy_optional(const Base_Type* other_value)
2352 {
2353 if (other_value->is_present()) {
2354 const Record_Type* other_rec = static_cast<const Record_Type*>(other_value->get_opt_value());
2355 copy_value(other_rec);
2356 } else if (other_value->is_bound()) {
2357 set_selection(OMIT_VALUE);
2358 err_descr = NULL;
2359 } else {
2360 TTCN_error("Initialization of a record/set template with an unbound optional field.");
2361 }
2362 }
2363
2364 void Record_Template::set_type(template_sel template_type, int list_length)
2365 {
2366 if (template_type != VALUE_LIST && template_type != COMPLEMENTED_LIST)
2367 TTCN_error("Setting an invalid list for a template of type %s.", get_descriptor()->name);
2368 clean_up();
2369 set_selection(template_type);
2370 value_list.n_values = list_length;
2371 value_list.list_value = (Record_Template**)allocate_pointers(value_list.n_values);
2372 for (int list_count = 0; list_count < value_list.n_values; list_count++)
2373 value_list.list_value[list_count] = create();
2374 }
2375
2376 Record_Template* Record_Template::get_list_item(int list_index) const
2377 {
2378 if (template_selection != VALUE_LIST && template_selection != COMPLEMENTED_LIST)
2379 TTCN_error("Accessing a list element of a non-list template of type %s.", get_descriptor()->name);
2380 if (list_index >= value_list.n_values || list_index < 0)
2381 TTCN_error("Index overflow in a value list template of type %s.", get_descriptor()->name);
2382 return value_list.list_value[list_index];
2383 }
2384
2385 int Record_Template::size_of() const
2386 {
2387 if (is_ifpresent)
2388 TTCN_error("Performing sizeof() operation on a template of type %s "
2389 "which has an ifpresent attribute.", get_descriptor()->name);
2390 switch (template_selection)
2391 {
2392 case SPECIFIC_VALUE: {
2393 int my_size = 0;
2394 for (int elem_count = 0; elem_count < single_value.n_elements; elem_count++)
2395 if (single_value.value_elements[elem_count]->is_present()) my_size++;
2396 return my_size;
2397 }
2398 case VALUE_LIST: {
2399 if (value_list.n_values<1)
2400 TTCN_error("Internal error: Performing sizeof() operation on a template of type %s containing an empty list.", get_descriptor()->name);
2401 int item_size = value_list.list_value[0]->size_of();
2402 for (int i = 1; i < value_list.n_values; i++)
2403 if (value_list.list_value[i]->size_of()!=item_size)
2404 TTCN_error("Performing sizeof() operation on a template of type %s containing a value list with different sizes.", get_descriptor()->name);
2405 return item_size;
2406 }
2407 case OMIT_VALUE:
2408 TTCN_error("Performing sizeof() operation on a template of type %s containing omit value.", get_descriptor()->name);
2409 case ANY_VALUE:
2410 case ANY_OR_OMIT:
2411 TTCN_error("Performing sizeof() operation on a template of type %s containing */? value.", get_descriptor()->name);
2412 case COMPLEMENTED_LIST:
2413 TTCN_error("Performing sizeof() operation on a template of type %s containing complemented list.", get_descriptor()->name);
2414 default:
2415 TTCN_error("Performing sizeof() operation on an uninitialized/unsupported template of type %s.", get_descriptor()->name);
2416 }
2417 return 0;
2418 }
2419
2420 boolean Record_Template::is_value() const
2421 {
2422 if (template_selection != SPECIFIC_VALUE || is_ifpresent) return FALSE;
2423 for (int elem_count = 0; elem_count < single_value.n_elements; elem_count++) {
2424 const Base_Template* tmpl_elem = single_value.value_elements[elem_count];
2425 if (tmpl_elem->get_selection()!=OMIT_VALUE && !tmpl_elem->is_value()) return FALSE;
2426 }
2427 return TRUE;
2428 }
2429
2430 void Record_Template::valueofv(Base_Type* value) const
2431 {
2432 if (template_selection != SPECIFIC_VALUE || is_ifpresent)
2433 TTCN_error("Performing a valueof or send operation on a non-specific template of type %s.", get_descriptor()->name);
2434 Record_Type* rec_value = static_cast<Record_Type*>(value);
2435 const int* optional_indexes = rec_value->get_optional_indexes();
2436 int next_optional_idx = 0;
2437 for (int elem_count = 0; elem_count < single_value.n_elements; elem_count++) {
2438 boolean is_optional = optional_indexes && (optional_indexes[next_optional_idx]==elem_count);
2439 if (is_optional) {
2440 if (single_value.value_elements[elem_count]->get_selection()==OMIT_VALUE) {
2441 rec_value->get_at(elem_count)->set_to_omit();
2442 } else {
2443 rec_value->get_at(elem_count)->set_to_present(); // create instance of optional value object
2444 single_value.value_elements[elem_count]->valueofv(rec_value->get_at(elem_count)->get_opt_value());
2445 }
2446 } else {
2447 single_value.value_elements[elem_count]->valueofv(rec_value->get_at(elem_count));
2448 }
2449 if (is_optional) next_optional_idx++;
2450 }
2451 rec_value->set_err_descr(err_descr);
2452 }
2453
2454 void Record_Template::set_value(template_sel other_value)
2455 {
2456 check_single_selection(other_value);
2457 clean_up();
2458 set_selection(other_value);
2459 err_descr = NULL;
2460 }
2461
2462 Base_Template* Record_Template::get_at(int index_value)
2463 {
2464 set_specific();
2465 if (index_value < 0 || index_value >= single_value.n_elements)
2466 TTCN_error("Internal error: accessing an element of a template of type %s using an "
2467 "invalid index: %d.", get_descriptor()->name, index_value);
2468 return single_value.value_elements[index_value];
2469 }
2470
2471 const Base_Template* Record_Template::get_at(int index_value) const
2472 {
2473 if (index_value < 0 || index_value >= single_value.n_elements)
2474 TTCN_error("Internal error: accessing an element of a template of type %s using an "
2475 "invalid index: %d.", get_descriptor()->name, index_value);
2476 if (template_selection != SPECIFIC_VALUE)
2477 TTCN_error("Accessing field %s of a non-specific template of type %s.",
2478 fld_name(index_value), get_descriptor()->name);
2479 return single_value.value_elements[index_value];
2480 }
2481
2482 Base_Template* Record_Template::clone() const
2483 {
2484 Record_Template* rec = create();
2485 rec->copy_template(*this);
2486 return rec;
2487 }
2488
2489 void Record_Template::log() const
2490 {
2491 switch (template_selection) {
2492 case SPECIFIC_VALUE:
2493 if (single_value.n_elements > 0) {
2494 TTCN_Logger::log_event_str("{ ");
2495 for (int elem_count = 0; elem_count < single_value.n_elements; elem_count++) {
2496 if (elem_count > 0) TTCN_Logger::log_event_str(", ");
2497 TTCN_Logger::log_event_str(fld_name(elem_count));
2498 TTCN_Logger::log_event_str(" := ");
2499 single_value.value_elements[elem_count]->log();
2500 }
2501 TTCN_Logger::log_event_str(" }");
2502 } else TTCN_Logger::log_event_str("{ }");
2503 break;
2504 case COMPLEMENTED_LIST:
2505 TTCN_Logger::log_event_str("complement ");
2506 // no break
2507 case VALUE_LIST:
2508 TTCN_Logger::log_char('(');
2509 for (int list_count = 0; list_count < value_list.n_values; list_count++) {
2510 if (list_count > 0) TTCN_Logger::log_event_str(", ");
2511 value_list.list_value[list_count]->log();
2512 }
2513 TTCN_Logger::log_char(')');
2514 break;
2515 default:
2516 log_generic();
2517 break;
2518 }
2519 log_ifpresent();
2520 if (err_descr) err_descr->log();
2521 }
2522
2523 boolean Record_Template::matchv(const Base_Type* other_value,
2524 boolean legacy) const
2525 {
2526 switch (template_selection) {
2527 case ANY_VALUE:
2528 case ANY_OR_OMIT:
2529 return TRUE;
2530 case OMIT_VALUE:
2531 return FALSE;
2532 case SPECIFIC_VALUE: {
2533 const Record_Type* other_rec = static_cast<const Record_Type*>(other_value);
2534 const int* optional_indexes = other_rec->get_optional_indexes();
2535 int next_optional_idx = 0;
2536 for (int elem_count = 0; elem_count < single_value.n_elements; elem_count++) {
2537 boolean is_optional = optional_indexes && (optional_indexes[next_optional_idx]==elem_count);
2538 const Base_Template* elem_tmpl = single_value.value_elements[elem_count];
2539 const Base_Type* elem_value = other_rec->get_at(elem_count);
2540 if (!elem_value->is_bound()) return FALSE;
2541 boolean elem_match = is_optional ?
2542 ( elem_value->ispresent() ? elem_tmpl->matchv(elem_value->get_opt_value(), legacy) : elem_tmpl->match_omit(legacy) ) :
2543 elem_tmpl->matchv(other_rec->get_at(elem_count), legacy);
2544 if (!elem_match) return FALSE;
2545 if (is_optional) next_optional_idx++;
2546 }
2547 } return TRUE;
2548 case VALUE_LIST:
2549 case COMPLEMENTED_LIST:
2550 for (int list_count = 0; list_count < value_list.n_values; list_count++)
2551 if (value_list.list_value[list_count]->matchv(other_value, legacy)) return template_selection == VALUE_LIST;
2552 return template_selection == COMPLEMENTED_LIST;
2553 default:
2554 TTCN_error("Matching an uninitialized/unsupported template of type %s.", get_descriptor()->name);
2555 }
2556 return FALSE;
2557 }
2558
2559 void Record_Template::log_matchv(const Base_Type* match_value, boolean legacy) const
2560 {
2561 if (TTCN_Logger::VERBOSITY_COMPACT == TTCN_Logger::get_matching_verbosity()) {
2562 if (matchv(match_value, legacy)) {
2563 TTCN_Logger::print_logmatch_buffer();
2564 TTCN_Logger::log_event_str(" matched");
2565 } else {
2566 if (template_selection == SPECIFIC_VALUE) {
2567 size_t previous_size = TTCN_Logger::get_logmatch_buffer_len();
2568 const Record_Type* match_rec = static_cast<const Record_Type*>(match_value);
2569 const int* optional_indexes = match_rec->get_optional_indexes();
2570 int next_optional_idx = 0;
2571 for (int elem_count = 0; elem_count < single_value.n_elements; elem_count++) {
2572 boolean is_optional = optional_indexes && (optional_indexes[next_optional_idx]==elem_count);
2573 const Base_Template* elem_tmpl = single_value.value_elements[elem_count];
2574 const Base_Type* elem_value = match_rec->get_at(elem_count);
2575 if (is_optional) {
2576 if (elem_value->ispresent()) {
2577 if (!elem_tmpl->matchv(elem_value->get_opt_value(), legacy)) {
2578 TTCN_Logger::log_logmatch_info(".%s", fld_name(elem_count));
2579 elem_tmpl->log_matchv(elem_value->get_opt_value(), legacy);
2580 TTCN_Logger::set_logmatch_buffer_len(previous_size);
2581 }
2582 } else {
2583 if (!elem_tmpl->match_omit(legacy)) {
2584 TTCN_Logger::log_logmatch_info(".%s := omit with ", fld_name(elem_count));
2585 TTCN_Logger::print_logmatch_buffer();
2586 elem_tmpl->log();
2587 TTCN_Logger::log_event_str(" unmatched");
2588 TTCN_Logger::set_logmatch_buffer_len(previous_size);
2589 }
2590 }
2591 } else {//mandatory
2592 if (!elem_tmpl->matchv(elem_value, legacy)) {
2593 TTCN_Logger::log_logmatch_info(".%s", fld_name(elem_count));
2594 elem_tmpl->log_matchv(elem_value, legacy);
2595 TTCN_Logger::set_logmatch_buffer_len(previous_size);
2596 }
2597 }//if
2598 if (is_optional) next_optional_idx++;
2599 }//for
2600 } else {
2601 TTCN_Logger::print_logmatch_buffer();
2602 match_value->log();
2603 TTCN_Logger::log_event_str(" with ");
2604 log();
2605 TTCN_Logger::log_event_str(" unmatched");
2606 }
2607 }
2608 } else {
2609 if (template_selection == SPECIFIC_VALUE) {
2610 const Record_Type* match_rec = static_cast<const Record_Type*>(match_value);
2611 const int* optional_indexes = match_rec->get_optional_indexes();
2612 int next_optional_idx = 0;
2613 TTCN_Logger::log_event_str("{ ");
2614 for (int elem_count = 0; elem_count < single_value.n_elements; elem_count++) {
2615 boolean is_optional = optional_indexes && (optional_indexes[next_optional_idx]==elem_count);
2616 const Base_Template* elem_tmpl = single_value.value_elements[elem_count];
2617 const Base_Type* elem_value = match_rec->get_at(elem_count);
2618 if (elem_count) TTCN_Logger::log_event_str(", ");
2619 TTCN_Logger::log_event_str(fld_name(elem_count));
2620 TTCN_Logger::log_event_str(" := ");
2621 if (is_optional) {
2622 if (elem_value->ispresent()) elem_tmpl->log_matchv(elem_value->get_opt_value(), legacy);
2623 else {
2624 TTCN_Logger::log_event_str("omit with ");
2625 elem_tmpl->log();
2626 if (elem_tmpl->match_omit(legacy)) TTCN_Logger::log_event_str(" matched");
2627 else TTCN_Logger::log_event_str(" unmatched");
2628 }
2629 } else {
2630 elem_tmpl->log_matchv(elem_value, legacy);
2631 }
2632 if (is_optional) next_optional_idx++;
2633 }
2634 TTCN_Logger::log_event_str(" }");
2635 } else {
2636 match_value->log();
2637 TTCN_Logger::log_event_str(" with ");
2638 log();
2639 if (matchv(match_value, legacy)) TTCN_Logger::log_event_str(" matched");
2640 else TTCN_Logger::log_event_str(" unmatched");
2641 }
2642 }
2643 }
2644
2645 void Record_Template::encode_text(Text_Buf& text_buf) const
2646 {
2647 encode_text_base(text_buf);
2648 switch (template_selection) {
2649 case SPECIFIC_VALUE:
2650 for (int elem_count = 0; elem_count < single_value.n_elements; elem_count++)
2651 single_value.value_elements[elem_count]->encode_text(text_buf);
2652 break;
2653 case OMIT_VALUE:
2654 case ANY_VALUE:
2655 case ANY_OR_OMIT:
2656 break;
2657 case VALUE_LIST:
2658 case COMPLEMENTED_LIST:
2659 text_buf.push_int(value_list.n_values);
2660 for (int list_count = 0; list_count < value_list.n_values; list_count++)
2661 value_list.list_value[list_count]->encode_text(text_buf);
2662 break;
2663 default:
2664 TTCN_error("Text encoder: Encoding an uninitialized/unsupported template"
2665 " of type %s.", get_descriptor()->name);
2666 }
2667 }
2668
2669 void Record_Template::decode_text(Text_Buf& text_buf)
2670 {
2671 clean_up();
2672 decode_text_base(text_buf);
2673 switch (template_selection) {
2674 case SPECIFIC_VALUE:
2675 template_selection = UNINITIALIZED_TEMPLATE; //set_specific will set it
2676 set_specific();
2677 for (int elem_count = 0; elem_count < single_value.n_elements; elem_count++)
2678 single_value.value_elements[elem_count]->decode_text(text_buf);
2679 break;
2680 case OMIT_VALUE:
2681 case ANY_VALUE:
2682 case ANY_OR_OMIT:
2683 break;
2684 case VALUE_LIST:
2685 case COMPLEMENTED_LIST:
2686 value_list.n_values = text_buf.pull_int().get_val();
2687 value_list.list_value = (Record_Template**)allocate_pointers(value_list.n_values);
2688 for (int list_count = 0; list_count < value_list.n_values; list_count++) {
2689 value_list.list_value[list_count] = create();
2690 value_list.list_value[list_count]->decode_text(text_buf);
2691 }
2692 break;
2693 default:
2694 TTCN_error("Text decoder: An unknown/unsupported selection was received in a template of type %s.", get_descriptor()->name);
2695 }
2696 }
2697
2698 boolean Record_Template::is_present(boolean legacy /*= FALSE*/) const
2699 {
2700 if (template_selection==UNINITIALIZED_TEMPLATE) return FALSE;
2701 return !match_omit(legacy);
2702 }
2703
2704 boolean Record_Template::match_omit(boolean legacy /*= FALSE*/) const
2705 {
2706 if (is_ifpresent) return TRUE;
2707 switch (template_selection) {
2708 case OMIT_VALUE:
2709 case ANY_OR_OMIT:
2710 return TRUE;
2711 case VALUE_LIST:
2712 case COMPLEMENTED_LIST:
2713 if (legacy) {
2714 // legacy behavior: 'omit' can appear in the value/complement list
2715 for (int i=0; i<value_list.n_values; i++)
2716 if (value_list.list_value[i]->match_omit()) return template_selection==VALUE_LIST;
2717 return template_selection==COMPLEMENTED_LIST;
2718 }
2719 // else fall through
2720 default:
2721 return FALSE;
2722 }
2723 return FALSE;
2724 }
2725
2726 void Record_Template::set_param(Module_Param& param)
2727 {
2728 if (dynamic_cast<Module_Param_Name*>(param.get_id()) != NULL &&
2729 param.get_id()->next_name()) {
2730 // Haven't reached the end of the module parameter name
2731 // => the name refers to one of the fields, not to the whole record
2732 char* param_field = param.get_id()->get_current_name();
2733 if (param_field[0] >= '0' && param_field[0] <= '9') {
2734 param.error("Unexpected array index in module parameter, expected a valid field"
2735 " name for record/set template type `%s'", get_descriptor()->name);
2736 }
2737 set_specific();
2738 for (int field_idx = 0; field_idx < single_value.n_elements; field_idx++) {
2739 if (strcmp(fld_name(field_idx), param_field) == 0) {
2740 single_value.value_elements[field_idx]->set_param(param);
2741 return;
2742 }
2743 }
2744 param.error("Field `%s' not found in record/set template type `%s'",
2745 param_field, get_descriptor()->name);
2746 }
2747
2748 param.basic_check(Module_Param::BC_TEMPLATE, "record/set template");
2749
2750 Module_Param_Ptr mp = &param;
2751 if (param.get_type() == Module_Param::MP_Reference) {
2752 mp = param.get_referenced_param();
2753 }
2754
2755 switch (mp->get_type()) {
2756 case Module_Param::MP_Omit:
2757 set_value(OMIT_VALUE);
2758 break;
2759 case Module_Param::MP_Any:
2760 set_value(ANY_VALUE);
2761 break;
2762 case Module_Param::MP_AnyOrNone:
2763 set_value(ANY_OR_OMIT);
2764 break;
2765 case Module_Param::MP_List_Template:
2766 case Module_Param::MP_ComplementList_Template: {
2767 Record_Template** list_items = (Record_Template**)
2768 allocate_pointers(mp->get_size());
2769 for (size_t i = 0; i < mp->get_size(); i++) {
2770 list_items[i] = create();
2771 list_items[i]->set_param(*mp->get_elem(i));
2772 }
2773 clean_up();
2774 template_selection = mp->get_type() == Module_Param::MP_List_Template ?
2775 VALUE_LIST : COMPLEMENTED_LIST;
2776 value_list.n_values = mp->get_size();
2777 value_list.list_value = list_items;
2778 break; }
2779 case Module_Param::MP_Value_List:
2780 set_specific();
2781 if (single_value.n_elements<(int)mp->get_size()) {
2782 param.error("Record/set template of type %s has %d fields but list value has %d fields", get_descriptor()->name, single_value.n_elements, (int)mp->get_size());
2783 }
2784 for (size_t i=0; i<mp->get_size(); i++) {
2785 Module_Param* mp_field = mp->get_elem(i);
2786 if (mp_field->get_type()!=Module_Param::MP_NotUsed) {
2787 get_at((int)i)->set_param(*mp_field);
2788 }
2789 }
2790 break;
2791 case Module_Param::MP_Assignment_List:
2792 set_specific();
2793 for (size_t i=0; i<mp->get_size(); ++i) {
2794 Module_Param* const current = mp->get_elem(i);
2795 bool found = false;
2796 for (int j=0; j<single_value.n_elements; ++j) {
2797 if (!strcmp(fld_name(j), current->get_id()->get_name())) {
2798 if (current->get_type()!=Module_Param::MP_NotUsed) {
2799 get_at(j)->set_param(*current);
2800 }
2801 found = true;
2802 break;
2803 }
2804 }
2805 if (!found) {
2806 current->error("Non existent field name in type %s: %s.", get_descriptor()->name, current->get_id()->get_name());
2807 }
2808 }
2809 break;
2810 default:
2811 param.type_error("record/set template", get_descriptor()->name);
2812 }
2813 is_ifpresent = param.get_ifpresent() || mp->get_ifpresent();
2814 }
2815
2816 Module_Param* Record_Template::get_param(Module_Param_Name& param_name) const
2817 {
2818 if (param_name.next_name()) {
2819 // Haven't reached the end of the module parameter name
2820 // => the name refers to one of the fields, not to the whole record
2821 char* param_field = param_name.get_current_name();
2822 if (param_field[0] >= '0' && param_field[0] <= '9') {
2823 TTCN_error("Unexpected array index in module parameter reference, "
2824 "expected a valid field name for record/set template type `%s'",
2825 get_descriptor()->name);
2826 }
2827 for (int field_idx = 0; field_idx < single_value.n_elements; field_idx++) {
2828 if (strcmp(fld_name(field_idx), param_field) == 0) {
2829 return get_at(field_idx)->get_param(param_name);
2830 }
2831 }
2832 TTCN_error("Field `%s' not found in record/set type `%s'",
2833 param_field, get_descriptor()->name);
2834 }
2835 Module_Param* mp = NULL;
2836 switch (template_selection) {
2837 case UNINITIALIZED_TEMPLATE:
2838 mp = new Module_Param_Unbound();
2839 break;
2840 case OMIT_VALUE:
2841 mp = new Module_Param_Omit();
2842 break;
2843 case ANY_VALUE:
2844 mp = new Module_Param_Any();
2845 break;
2846 case ANY_OR_OMIT:
2847 mp = new Module_Param_AnyOrNone();
2848 break;
2849 case SPECIFIC_VALUE: {
2850 mp = new Module_Param_Assignment_List();
2851 for (int i = 0; i < single_value.n_elements; ++i) {
2852 Module_Param* mp_field = get_at(i)->get_param(param_name);
2853 mp_field->set_id(new Module_Param_FieldName(mcopystr(fld_name(i))));
2854 mp->add_elem(mp_field);
2855 }
2856 break; }
2857 case VALUE_LIST:
2858 case COMPLEMENTED_LIST: {
2859 if (template_selection == VALUE_LIST) {
2860 mp = new Module_Param_List_Template();
2861 }
2862 else {
2863 mp = new Module_Param_ComplementList_Template();
2864 }
2865 for (int i = 0; i < value_list.n_values; ++i) {
2866 mp->add_elem(value_list.list_value[i]->get_param(param_name));
2867 }
2868 break; }
2869 default:
2870 break;
2871 }
2872 if (is_ifpresent) {
2873 mp->set_ifpresent();
2874 }
2875 return mp;
2876 }
2877
2878 void Record_Template::check_restriction(template_res t_res, const char* t_name,
2879 boolean legacy /* = FALSE */) const
2880 {
2881 if (template_selection==UNINITIALIZED_TEMPLATE) return;
2882 switch ((t_name&&(t_res==TR_VALUE))?TR_OMIT:t_res) {
2883 case TR_OMIT:
2884 if (template_selection==OMIT_VALUE) return;
2885 // no break
2886 case TR_VALUE:
2887 if (template_selection!=SPECIFIC_VALUE || is_ifpresent) break;
2888 for (int i=0; i<single_value.n_elements; i++)
2889 single_value.value_elements[i]->check_restriction(t_res, t_name ? t_name : get_descriptor()->name);
2890 return;
2891 case TR_PRESENT:
2892 if (!match_omit(legacy)) return;
2893 break;
2894 default:
2895 return;
2896 }
2897 TTCN_error("Restriction `%s' on template of type %s violated.",
2898 get_res_name(t_res), t_name ? t_name : get_descriptor()->name);
2899 }
2900
2901 ////////////////////////////////////////////////////////////////////////////////
2902
2903 Empty_Record_Template::Empty_Record_Template(): Base_Template()
2904 {
2905 }
2906
2907 Empty_Record_Template::Empty_Record_Template(template_sel other_value):
2908 Base_Template(other_value)
2909 {
2910 check_single_selection(other_value);
2911 }
2912
2913 Empty_Record_Template::~Empty_Record_Template()
2914 {
2915 clean_up();
2916 }
2917
2918 void Empty_Record_Template::clean_up()
2919 {
2920 switch (template_selection) {
2921 case VALUE_LIST:
2922 case COMPLEMENTED_LIST:
2923 for (int elem_count = 0; elem_count < value_list.n_values; elem_count++)
2924 delete value_list.list_value[elem_count];
2925 free_pointers((void**)value_list.list_value);
2926 break;
2927 default:
2928 break;
2929 }
2930 template_selection = UNINITIALIZED_TEMPLATE;
2931 }
2932
2933 void Empty_Record_Template::copy_value(const Base_Type* other_value)
2934 {
2935 if (!other_value->is_bound())
2936 TTCN_error("Initialization of a record/set template with an unbound value.");
2937 set_selection(SPECIFIC_VALUE);
2938 }
2939
2940 void Empty_Record_Template::copy_template(const Empty_Record_Template& other_value)
2941 {
2942 switch (other_value.template_selection) {
2943 case SPECIFIC_VALUE:
2944 case OMIT_VALUE:
2945 case ANY_VALUE:
2946 case ANY_OR_OMIT:
2947 break;
2948 case VALUE_LIST:
2949 case COMPLEMENTED_LIST:
2950 value_list.n_values = other_value.value_list.n_values;
2951 value_list.list_value = (Empty_Record_Template**)allocate_pointers(value_list.n_values);
2952 for (int list_count = 0; list_count < value_list.n_values; list_count++)
2953 value_list.list_value[list_count] = static_cast<Empty_Record_Template*>(other_value.value_list.list_value[list_count]->clone());
2954 break;
2955 default:
2956 TTCN_error("Copying an uninitialized/unsupported record/set template.");
2957 break;
2958 }
2959 set_selection(other_value);
2960 }
2961
2962 void Empty_Record_Template::copy_optional(const Base_Type* other_value)
2963 {
2964 if (other_value->is_present()) {
2965 const Empty_Record_Type* other_rec = static_cast<const Empty_Record_Type*>(other_value->get_opt_value());
2966 copy_value(other_rec);
2967 } else if (other_value->is_bound()) {
2968 set_selection(OMIT_VALUE);
2969 } else {
2970 TTCN_error("Initialization of a record/set template with an unbound optional field.");
2971 }
2972 }
2973
2974 void Empty_Record_Template::set_type(template_sel template_type, int list_length)
2975 {
2976 if (template_type != VALUE_LIST && template_type != COMPLEMENTED_LIST)
2977 TTCN_error("Setting an invalid list for a template of type %s.", get_descriptor()->name);
2978 clean_up();
2979 set_selection(template_type);
2980 value_list.n_values = list_length;
2981 value_list.list_value = (Empty_Record_Template**)allocate_pointers(value_list.n_values);
2982 for (int list_count = 0; list_count < value_list.n_values; list_count++)
2983 value_list.list_value[list_count] = create();
2984 }
2985
2986 Empty_Record_Template* Empty_Record_Template::get_list_item(int list_index) const
2987 {
2988 if (template_selection != VALUE_LIST && template_selection != COMPLEMENTED_LIST)
2989 TTCN_error("Accessing a list element of a non-list template of type %s.", get_descriptor()->name);
2990 if (list_index >= value_list.n_values || list_index < 0)
2991 TTCN_error("Index overflow in a value list template of type %s.", get_descriptor()->name);
2992 return value_list.list_value[list_index];
2993 }
2994
2995 int Empty_Record_Template::size_of() const
2996 {
2997 if (is_ifpresent)
2998 TTCN_error("Performing sizeof() operation on a template of type %s "
2999 "which has an ifpresent attribute.", get_descriptor()->name);
3000 switch (template_selection)
3001 {
3002 case SPECIFIC_VALUE:
3003 return 0;
3004 case VALUE_LIST: {
3005 if (value_list.n_values<1)
3006 TTCN_error("Internal error: Performing sizeof() operation on a template of type %s containing an empty list.", get_descriptor()->name);
3007 int item_size = value_list.list_value[0]->size_of();
3008 for (int i = 1; i < value_list.n_values; i++)
3009 if (value_list.list_value[i]->size_of()!=item_size)
3010 TTCN_error("Performing sizeof() operation on a template of type %s containing a value list with different sizes.", get_descriptor()->name);
3011 return item_size;
3012 }
3013 case OMIT_VALUE:
3014 TTCN_error("Performing sizeof() operation on a template of type %s containing omit value.", get_descriptor()->name);
3015 case ANY_VALUE:
3016 case ANY_OR_OMIT:
3017 TTCN_error("Performing sizeof() operation on a template of type %s containing */? value.", get_descriptor()->name);
3018 case COMPLEMENTED_LIST:
3019 TTCN_error("Performing sizeof() operation on a template of type %s containing complemented list.", get_descriptor()->name);
3020 default:
3021 TTCN_error("Performing sizeof() operation on an uninitialized/unsupported template of type %s.", get_descriptor()->name);
3022 }
3023 return 0;
3024 }
3025
3026 boolean Empty_Record_Template::is_value() const
3027 {
3028 return (template_selection == SPECIFIC_VALUE && !is_ifpresent);
3029 }
3030
3031 void Empty_Record_Template::valueofv(Base_Type* value) const
3032 {
3033 if (template_selection != SPECIFIC_VALUE || is_ifpresent)
3034 TTCN_error("Performing a valueof or send operation on a non-specific template of type %s.", get_descriptor()->name);
3035 Empty_Record_Type* rec_value = static_cast<Empty_Record_Type*>(value);
3036 rec_value->set_null();
3037 }
3038
3039 void Empty_Record_Template::set_value(template_sel other_value)
3040 {
3041 check_single_selection(other_value);
3042 clean_up();
3043 set_selection(other_value);
3044 }
3045
3046 Base_Template* Empty_Record_Template::clone() const
3047 {
3048 Empty_Record_Template* rec = create();
3049 rec->copy_template(*this);
3050 return rec;
3051 }
3052
3053 void Empty_Record_Template::log() const
3054 {
3055 switch (template_selection) {
3056 case SPECIFIC_VALUE:
3057 TTCN_Logger::log_event_str("{ }");
3058 break;
3059 case COMPLEMENTED_LIST:
3060 TTCN_Logger::log_event_str("complement ");
3061 // no break
3062 case VALUE_LIST:
3063 TTCN_Logger::log_char('(');
3064 for (int list_count = 0; list_count < value_list.n_values; list_count++) {
3065 if (list_count > 0) TTCN_Logger::log_event_str(", ");
3066 value_list.list_value[list_count]->log();
3067 }
3068 TTCN_Logger::log_char(')');
3069 break;
3070 default:
3071 log_generic();
3072 break;
3073 }
3074 log_ifpresent();
3075 }
3076
3077 boolean Empty_Record_Template::matchv(const Base_Type* other_value,
3078 boolean legacy) const
3079 {
3080 switch (template_selection) {
3081 case ANY_VALUE:
3082 case ANY_OR_OMIT:
3083 return TRUE;
3084 case OMIT_VALUE:
3085 return FALSE;
3086 case SPECIFIC_VALUE:
3087 return TRUE;
3088 case VALUE_LIST:
3089 case COMPLEMENTED_LIST:
3090 for (int list_count = 0; list_count < value_list.n_values; list_count++)
3091 if (value_list.list_value[list_count]->matchv(other_value, legacy)) return template_selection == VALUE_LIST;
3092 return template_selection == COMPLEMENTED_LIST;
3093 default:
3094 TTCN_error("Matching an uninitialized/unsupported template of type %s.", get_descriptor()->name);
3095 }
3096 return FALSE;
3097 }
3098
3099 void Empty_Record_Template::log_matchv(const Base_Type* match_value, boolean legacy) const
3100 {
3101 match_value->log();
3102 TTCN_Logger::log_event_str(" with ");
3103 log();
3104 if (matchv(match_value, legacy)) TTCN_Logger::log_event_str(" matched");
3105 else TTCN_Logger::log_event_str(" unmatched");
3106 }
3107
3108 void Empty_Record_Template::encode_text(Text_Buf& text_buf) const
3109 {
3110 encode_text_base(text_buf);
3111 switch (template_selection) {
3112 case SPECIFIC_VALUE:
3113 case OMIT_VALUE:
3114 case ANY_VALUE:
3115 case ANY_OR_OMIT:
3116 break;
3117 case VALUE_LIST:
3118 case COMPLEMENTED_LIST:
3119 text_buf.push_int(value_list.n_values);
3120 for (int list_count = 0; list_count < value_list.n_values; list_count++)
3121 value_list.list_value[list_count]->encode_text(text_buf);
3122 break;
3123 default:
3124 TTCN_error("Text encoder: Encoding an uninitialized/unsupported template of type %s.", get_descriptor()->name);
3125 }
3126 }
3127
3128 void Empty_Record_Template::decode_text(Text_Buf& text_buf)
3129 {
3130 clean_up();
3131 decode_text_base(text_buf);
3132 switch (template_selection) {
3133 case SPECIFIC_VALUE:
3134 case OMIT_VALUE:
3135 case ANY_VALUE:
3136 case ANY_OR_OMIT:
3137 break;
3138 case VALUE_LIST:
3139 case COMPLEMENTED_LIST:
3140 value_list.n_values = text_buf.pull_int().get_val();
3141 value_list.list_value = (Empty_Record_Template**)allocate_pointers(value_list.n_values);
3142 for (int list_count = 0; list_count < value_list.n_values; list_count++) {
3143 value_list.list_value[list_count] = create();
3144 value_list.list_value[list_count]->decode_text(text_buf);
3145 }
3146 break;
3147 default:
3148 TTCN_error("Text decoder: An unknown/unsupported selection was received in a template of type %s.", get_descriptor()->name);
3149 }
3150 }
3151
3152 boolean Empty_Record_Template::is_present(boolean legacy /*= FALSE*/) const
3153 {
3154 if (template_selection==UNINITIALIZED_TEMPLATE) return FALSE;
3155 return !match_omit(legacy);
3156 }
3157
3158 boolean Empty_Record_Template::match_omit(boolean legacy /* = FALSE */) const
3159 {
3160 if (is_ifpresent) return TRUE;
3161 switch (template_selection) {
3162 case OMIT_VALUE:
3163 case ANY_OR_OMIT:
3164 return TRUE;
3165 case VALUE_LIST:
3166 case COMPLEMENTED_LIST:
3167 if (legacy) {
3168 // legacy behavior: 'omit' can appear in the value/complement list
3169 for (int i=0; i<value_list.n_values; i++)
3170 if (value_list.list_value[i]->match_omit()) return template_selection==VALUE_LIST;
3171 return template_selection==COMPLEMENTED_LIST;
3172 }
3173 // else fall through
3174 default:
3175 return FALSE;
3176 }
3177 return FALSE;
3178 }
3179
3180 void Empty_Record_Template::set_param(Module_Param& param)
3181 {
3182 param.basic_check(Module_Param::BC_TEMPLATE, "empty record/set template");
3183 Module_Param_Ptr mp = &param;
3184 if (param.get_type() == Module_Param::MP_Reference) {
3185 mp = param.get_referenced_param();
3186 }
3187 switch (mp->get_type()) {
3188 case Module_Param::MP_Omit:
3189 set_value(OMIT_VALUE);
3190 break;
3191 case Module_Param::MP_Any:
3192 set_value(ANY_VALUE);
3193 break;
3194 case Module_Param::MP_AnyOrNone:
3195 set_value(ANY_OR_OMIT);
3196 break;
3197 case Module_Param::MP_List_Template:
3198 case Module_Param::MP_ComplementList_Template: {
3199 Empty_Record_Template** list_items = (Empty_Record_Template**)
3200 allocate_pointers(mp->get_size());
3201 for (size_t i = 0; i < mp->get_size(); i++) {
3202 list_items[i] = create();
3203 list_items[i]->set_param(*mp->get_elem(i));
3204 }
3205 clean_up();
3206 template_selection = mp->get_type() == Module_Param::MP_List_Template ?
3207 VALUE_LIST : COMPLEMENTED_LIST;
3208 value_list.n_values = mp->get_size();
3209 value_list.list_value = list_items;
3210 break; }
3211 case Module_Param::MP_Value_List:
3212 if (mp->get_size()==0) {
3213 set_selection(SPECIFIC_VALUE);
3214 }
3215 else param.type_error("empty record/set template", get_descriptor()->name);
3216 break;
3217 default:
3218 param.type_error("empty record/set template", get_descriptor()->name);
3219 }
3220 is_ifpresent = param.get_ifpresent() || mp->get_ifpresent();
3221 }
3222
3223 Module_Param* Empty_Record_Template::get_param(Module_Param_Name& param_name) const
3224 {
3225 Module_Param* mp = NULL;
3226 switch (template_selection) {
3227 case UNINITIALIZED_TEMPLATE:
3228 mp = new Module_Param_Unbound();
3229 break;
3230 case OMIT_VALUE:
3231 mp = new Module_Param_Omit();
3232 break;
3233 case ANY_VALUE:
3234 mp = new Module_Param_Any();
3235 break;
3236 case ANY_OR_OMIT:
3237 mp = new Module_Param_AnyOrNone();
3238 break;
3239 case SPECIFIC_VALUE:
3240 mp = new Module_Param_Value_List();
3241 break;
3242 case VALUE_LIST:
3243 case COMPLEMENTED_LIST: {
3244 if (template_selection == VALUE_LIST) {
3245 mp = new Module_Param_List_Template();
3246 }
3247 else {
3248 mp = new Module_Param_ComplementList_Template();
3249 }
3250 for (int i = 0; i < value_list.n_values; ++i) {
3251 mp->add_elem(value_list.list_value[i]->get_param(param_name));
3252 }
3253 break; }
3254 default:
3255 break;
3256 }
3257 if (is_ifpresent) {
3258 mp->set_ifpresent();
3259 }
3260 return mp;
3261 }
3262
3263 #endif
This page took 0.100432 seconds and 5 git commands to generate.