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