Sync with 5.4.2
[deliverable/titan.core.git] / core / Component.cc
1 ///////////////////////////////////////////////////////////////////////////////
2 // Copyright (c) 2000-2015 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
12 #include "Component.hh"
13 #include "Logger.hh"
14 #include "Parameters.h"
15 #include "Param_Types.hh"
16 #include "Runtime.hh"
17 #include "Optional.hh"
18
19 #include "../common/dbgnew.hh"
20
21 COMPONENT::COMPONENT()
22 {
23 component_value = UNBOUND_COMPREF;
24 }
25
26 COMPONENT::COMPONENT(component other_value)
27 {
28 component_value = other_value;
29 }
30
31 COMPONENT::COMPONENT(const COMPONENT& other_value)
32 : Base_Type(other_value)
33 {
34 if (other_value.component_value == UNBOUND_COMPREF)
35 TTCN_error("Copying an unbound component reference.");
36 component_value = other_value.component_value;
37 }
38
39 COMPONENT& COMPONENT::operator=(component other_value)
40 {
41 component_value = other_value;
42 return *this;
43 }
44
45 COMPONENT& COMPONENT::operator=(const COMPONENT& other_value)
46 {
47 if (other_value.component_value == UNBOUND_COMPREF)
48 TTCN_error("Assignment of an unbound component reference.");
49 component_value = other_value.component_value;
50 return *this;
51 }
52
53 boolean COMPONENT::operator==(component other_value) const
54 {
55 if (component_value == UNBOUND_COMPREF) TTCN_error("The left operand of "
56 "comparison is an unbound component reference.");
57 return component_value == other_value;
58 }
59
60 boolean COMPONENT::operator==(const COMPONENT& other_value) const
61 {
62 if (component_value == UNBOUND_COMPREF) TTCN_error("The left operand of "
63 "comparison is an unbound component reference.");
64 if (other_value.component_value == UNBOUND_COMPREF) TTCN_error("The right "
65 "operand of comparison is an unbound component reference.");
66 return component_value == other_value.component_value;
67 }
68
69 COMPONENT::operator component() const
70 {
71 if (component_value == UNBOUND_COMPREF) TTCN_error("Using the value of an "
72 "unbound component reference.");
73 return component_value;
74 }
75
76 void COMPONENT::log() const
77 {
78 if (component_value != UNBOUND_COMPREF)
79 log_component_reference(component_value);
80 else TTCN_Logger::log_event_unbound();
81 }
82
83 alt_status COMPONENT::done() const
84 {
85 if (component_value == UNBOUND_COMPREF) TTCN_error("Performing done "
86 "operation on an unbound component reference.");
87 return TTCN_Runtime::component_done(component_value);
88 }
89
90 alt_status COMPONENT::killed() const
91 {
92 if (component_value == UNBOUND_COMPREF) TTCN_error("Performing killed "
93 "operation on an unbound component reference.");
94 return TTCN_Runtime::component_killed(component_value);
95 }
96
97 boolean COMPONENT::running() const
98 {
99 if (component_value == UNBOUND_COMPREF) TTCN_error("Performing running "
100 "operation on an unbound component reference.");
101 return TTCN_Runtime::component_running(component_value);
102 }
103
104 boolean COMPONENT::alive() const
105 {
106 if (component_value == UNBOUND_COMPREF) TTCN_error("Performing alive "
107 "operation on an unbound component reference.");
108 return TTCN_Runtime::component_alive(component_value);
109 }
110
111 void COMPONENT::stop() const
112 {
113 if (component_value == UNBOUND_COMPREF) TTCN_error("Performing stop "
114 "operation on an unbound component reference.");
115 TTCN_Runtime::stop_component(component_value);
116 }
117
118 void COMPONENT::kill() const
119 {
120 if (component_value == UNBOUND_COMPREF) TTCN_error("Performing kill "
121 "operation on an unbound component reference.");
122 TTCN_Runtime::kill_component(component_value);
123 }
124
125 void COMPONENT::set_param(Module_Param& param) {
126 param.basic_check(Module_Param::BC_VALUE, "component reference (integer or null) value");
127 Module_Param_Ptr mp = &param;
128 if (param.get_type() == Module_Param::MP_Reference) {
129 mp = param.get_referenced_param();
130 }
131 if (Ttcn_String_Parsing::happening()) {
132 // accept all component values in case it's a string2ttcn operation
133 switch (mp->get_type()) {
134 case Module_Param::MP_Integer:
135 component_value = (component)mp->get_integer()->get_val();
136 break;
137 case Module_Param::MP_Ttcn_Null:
138 component_value = NULL_COMPREF;
139 break;
140 case Module_Param::MP_Ttcn_mtc:
141 component_value = MTC_COMPREF;
142 break;
143 case Module_Param::MP_Ttcn_system:
144 component_value = SYSTEM_COMPREF;
145 break;
146 default:
147 param.type_error("component reference (integer or null) value");
148 }
149 }
150 else {
151 // only accept the null value if it's a module parameter
152 if (Module_Param::MP_Ttcn_Null != mp->get_type()) {
153 param.error("Only the 'null' value is allowed for module parameters of type 'component'.");
154 }
155 component_value = NULL_COMPREF;
156 }
157 }
158
159 Module_Param* COMPONENT::get_param(Module_Param_Name& /* param_name */) const
160 {
161 if (!is_bound()) {
162 return new Module_Param_Unbound();
163 }
164 return new Module_Param_Ttcn_Null();
165 }
166
167 void COMPONENT::encode_text(Text_Buf& text_buf) const
168 {
169 if (component_value == UNBOUND_COMPREF) TTCN_error("Text encoder: Encoding "
170 "an unbound component reference.");
171 text_buf.push_int((int)component_value);
172 switch (component_value) {
173 case NULL_COMPREF:
174 case MTC_COMPREF:
175 case SYSTEM_COMPREF:
176 break;
177 default:
178 text_buf.push_string(get_component_name(component_value));
179 break;
180 }
181 }
182
183 void COMPONENT::decode_text(Text_Buf& text_buf)
184 {
185 component_value = (component)text_buf.pull_int().get_val();
186 switch (component_value) {
187 case NULL_COMPREF:
188 case MTC_COMPREF:
189 case SYSTEM_COMPREF:
190 break;
191 default:
192 char *component_name = text_buf.pull_string();
193 register_component_name(component_value, component_name);
194 delete [] component_name;
195 break;
196 }
197 }
198
199 boolean operator==(component component_value, const COMPONENT& other_value)
200 {
201 if (other_value.component_value == UNBOUND_COMPREF) TTCN_error("The right "
202 "operand of comparison is an unbound component reference.");
203 return component_value == other_value.component_value;
204 }
205
206 unsigned int COMPONENT::n_component_names = 0;
207 struct COMPONENT::component_name_struct {
208 component component_reference;
209 char *component_name;
210 } *COMPONENT::component_names = NULL;
211
212 void COMPONENT::register_component_name(component component_reference,
213 const char *component_name)
214 {
215 if (self.component_value == component_reference) {
216 // the own name of the component will not be registered,
217 // but check whether we got the right string
218 const char *local_name = TTCN_Runtime::get_component_name();
219 if (component_name == NULL || component_name[0] == '\0') {
220 if (local_name != NULL) {
221 TTCN_error("Internal error: Trying to register the component "
222 "reference of this PTC without any name, but this "
223 "component has name %s.", local_name);
224 }
225 } else {
226 if (local_name == NULL) {
227 TTCN_error("Internal error: Trying to register the component "
228 "reference of this PTC with name %s, but this component "
229 "does not have name.", component_name);
230 } else if (strcmp(component_name, local_name)) {
231 TTCN_error("Internal error: Trying to register the component "
232 "reference of this PTC with name %s, but this component "
233 "has name %s.", component_name, local_name);
234 }
235 }
236 return;
237 }
238 unsigned int min = 0;
239 if (n_component_names > 0) {
240 // perform a binary search to find the place for the component reference
241 unsigned int max = n_component_names - 1;
242 while (min < max) {
243 unsigned int mid = min + (max - min) / 2;
244 if (component_names[mid].component_reference < component_reference)
245 min = mid + 1;
246 else if (component_names[mid].component_reference ==
247 component_reference) {
248 min = mid;
249 break;
250 } else max = mid;
251 }
252 if (component_names[min].component_reference == component_reference) {
253 // the component reference is already registered
254 const char *stored_name = component_names[min].component_name;
255 if (component_name == NULL || component_name[0] == '\0') {
256 if (stored_name != NULL) {
257 TTCN_error("Internal error: Trying to register component "
258 "reference %d without any name, but this component "
259 "reference is already registered with name %s.",
260 component_reference, stored_name);
261 }
262 } else {
263 if (stored_name == NULL) {
264 TTCN_error("Internal error: Trying to register component "
265 "reference %d with name %s, but this component "
266 "reference is already registered without name.",
267 component_reference, component_name);
268 } else if (strcmp(component_name, stored_name)) {
269 TTCN_error("Internal error: Trying to register component "
270 "reference %d with name %s, but this component "
271 "reference is already registered with a different "
272 "name (%s).", component_reference, component_name,
273 stored_name);
274 }
275 }
276 return;
277 } else {
278 if (component_names[min].component_reference < component_reference)
279 min++;
280 // the component reference will be inserted before the index "min"
281 component_names =
282 (component_name_struct*)Realloc(component_names,
283 (n_component_names + 1) * sizeof(*component_names));
284 memmove(component_names + min + 1, component_names + min,
285 (n_component_names - min) * sizeof(*component_names));
286 }
287 } else {
288 // this is the first component reference to be registered
289 component_names =
290 (component_name_struct*)Malloc(sizeof(*component_names));
291 }
292 component_names[min].component_reference = component_reference;
293 if (component_name == NULL || component_name[0] == '\0')
294 component_names[min].component_name = NULL;
295 else component_names[min].component_name = mcopystr(component_name);
296 n_component_names++;
297 }
298
299 const char *COMPONENT::get_component_name(component component_reference)
300 {
301 if (self.component_value == component_reference) {
302 // the own name of the PTC is not registered
303 return TTCN_Runtime::get_component_name();
304 } else if (n_component_names > 0) {
305 unsigned int min = 0, max = n_component_names - 1;
306 while (min < max) {
307 unsigned int mid = min + (max - min) / 2;
308 if (component_names[mid].component_reference < component_reference)
309 min = mid + 1;
310 else if (component_names[mid].component_reference ==
311 component_reference)
312 return component_names[mid].component_name;
313 else max = mid;
314 }
315 if (component_names[min].component_reference != component_reference)
316 TTCN_error("Internal error: Trying to get the name of PTC with "
317 "component reference %d, but the name of the component "
318 "is not registered.", component_reference);
319 return component_names[min].component_name;
320 } else {
321 TTCN_error("Internal error: Trying to get the name of PTC with "
322 "component reference %d, but there are no component names "
323 "registered.", component_reference);
324 return NULL;
325 }
326 }
327
328 void COMPONENT::clear_component_names()
329 {
330 for (unsigned int i = 0; i < n_component_names; i++)
331 Free(component_names[i].component_name);
332 Free(component_names);
333 n_component_names = 0;
334 component_names = NULL;
335 }
336
337 void COMPONENT::log_component_reference(component component_reference)
338 {
339 switch (component_reference) {
340 case NULL_COMPREF:
341 TTCN_Logger::log_event_str("null");
342 break;
343 case MTC_COMPREF:
344 TTCN_Logger::log_event_str("mtc");
345 break;
346 case SYSTEM_COMPREF:
347 TTCN_Logger::log_event_str("system");
348 break;
349 default:
350 const char *component_name = get_component_name(component_reference);
351 if (component_name != NULL) TTCN_Logger::log_event("%s(%d)",
352 component_name, component_reference);
353 else TTCN_Logger::log_event("%d", component_reference);
354 break;
355 }
356 }
357
358 // get_component_string is suspiciously similar to log_component_reference.
359 // It would be trivially easy to implement log_... with get_...
360 // but it would involve a runtime penalty, because get_component_string
361 // returns a newly allocated string which must be freed, whereas log_...
362 // uses fixed strings. So the current implementation pays for speed with size.
363 // Perhaps log_component_reference will go away one day.
364 char *COMPONENT::get_component_string(component component_reference)
365 {
366 switch (component_reference) {
367 case NULL_COMPREF:
368 return mcopystr("null");
369 case MTC_COMPREF:
370 return mcopystr("mtc");
371 case SYSTEM_COMPREF:
372 return mcopystr("system");
373 case CONTROL_COMPREF:
374 return mcopystr("control");
375 default:
376 const char *component_name = get_component_name(component_reference);
377 if (component_name != NULL) return mprintf("%s(%d)",
378 component_name, component_reference);
379 else return mprintf("%d", component_reference);
380 }
381 }
382
383 COMPONENT self;
384
385 void COMPONENT_template::clean_up()
386 {
387 if (template_selection == VALUE_LIST
388 ||template_selection == COMPLEMENTED_LIST)
389 delete [] value_list.list_value;
390 template_selection = UNINITIALIZED_TEMPLATE;
391 }
392
393 void COMPONENT_template::copy_template(const COMPONENT_template& other_value)
394 {
395 switch (other_value.template_selection) {
396 case SPECIFIC_VALUE:
397 single_value = other_value.single_value;
398 break;
399 case OMIT_VALUE:
400 case ANY_VALUE:
401 case ANY_OR_OMIT:
402 break;
403 case VALUE_LIST:
404 case COMPLEMENTED_LIST:
405 value_list.n_values = other_value.value_list.n_values;
406 value_list.list_value = new COMPONENT_template[value_list.n_values];
407 for (unsigned int i = 0; i < value_list.n_values; i++)
408 value_list.list_value[i].copy_template(
409 other_value.value_list.list_value[i]);
410 break;
411 default:
412 TTCN_error("Copying an uninitialized/unsupported component reference "
413 "template.");
414 }
415 set_selection(other_value);
416 }
417
418 COMPONENT_template::COMPONENT_template()
419 {
420
421 }
422
423 COMPONENT_template::COMPONENT_template(template_sel other_value)
424 : Base_Template(other_value)
425 {
426 check_single_selection(other_value);
427 }
428
429 COMPONENT_template::COMPONENT_template(component other_value)
430 : Base_Template(SPECIFIC_VALUE)
431 {
432 single_value = other_value;
433 }
434
435 COMPONENT_template::COMPONENT_template(const COMPONENT& other_value)
436 : Base_Template(SPECIFIC_VALUE)
437 {
438 if (other_value.component_value == UNBOUND_COMPREF)
439 TTCN_error("Creating a template from an unbound component reference.");
440 single_value = other_value.component_value;
441 }
442
443 COMPONENT_template::COMPONENT_template(const OPTIONAL<COMPONENT>& other_value)
444 {
445 switch (other_value.get_selection()) {
446 case OPTIONAL_PRESENT:
447 set_selection(SPECIFIC_VALUE);
448 single_value = (component)(const COMPONENT&)other_value;
449 break;
450 case OPTIONAL_OMIT:
451 set_selection(OMIT_VALUE);
452 break;
453 default:
454 TTCN_error("Creating a component reference template from an unbound "
455 "optional field.");
456 }
457 }
458
459 COMPONENT_template::COMPONENT_template(const COMPONENT_template& other_value)
460 : Base_Template()
461 {
462 copy_template(other_value);
463 }
464
465 COMPONENT_template::~COMPONENT_template()
466 {
467 clean_up();
468 }
469
470 COMPONENT_template& COMPONENT_template::operator=(template_sel other_value)
471 {
472 check_single_selection(other_value);
473 clean_up();
474 set_selection(other_value);
475 return *this;
476 }
477
478 COMPONENT_template& COMPONENT_template::operator=(component other_value)
479 {
480 clean_up();
481 set_selection(SPECIFIC_VALUE);
482 single_value = other_value;
483 return *this;
484 }
485
486 COMPONENT_template& COMPONENT_template::operator=(const COMPONENT& other_value)
487 {
488 if (other_value.component_value == UNBOUND_COMPREF)
489 TTCN_error("Assignment of an unbound component reference to a "
490 "template.");
491 return *this = other_value.component_value;
492 }
493
494 COMPONENT_template& COMPONENT_template::operator=
495 (const OPTIONAL<COMPONENT>& other_value)
496 {
497 clean_up();
498 switch (other_value.get_selection()) {
499 case OPTIONAL_PRESENT:
500 set_selection(SPECIFIC_VALUE);
501 single_value = (component)(const COMPONENT&)other_value;
502 break;
503 case OPTIONAL_OMIT:
504 set_selection(OMIT_VALUE);
505 break;
506 default:
507 TTCN_error("Assignment of an unbound optional field to a component "
508 "reference template.");
509 }
510 return *this;
511 }
512
513 COMPONENT_template& COMPONENT_template::operator=
514 (const COMPONENT_template& other_value)
515 {
516 if (&other_value != this) {
517 clean_up();
518 copy_template(other_value);
519 }
520 return *this;
521 }
522
523 boolean COMPONENT_template::match(component other_value,
524 boolean /* legacy */) const
525 {
526 switch (template_selection) {
527 case SPECIFIC_VALUE:
528 return single_value == other_value;
529 case OMIT_VALUE:
530 return FALSE;
531 case ANY_VALUE:
532 case ANY_OR_OMIT:
533 return TRUE;
534 case VALUE_LIST:
535 case COMPLEMENTED_LIST:
536 for (unsigned int i = 0; i < value_list.n_values; i++)
537 if (value_list.list_value[i].match(other_value))
538 return template_selection == VALUE_LIST;
539 return template_selection == COMPLEMENTED_LIST;
540 default:
541 TTCN_error("Matching an uninitialized/unsupported component reference "
542 "template.");
543 }
544 return FALSE;
545 }
546
547 boolean COMPONENT_template::match(const COMPONENT& other_value,
548 boolean /* legacy */) const
549 {
550 if (other_value.component_value == UNBOUND_COMPREF)
551 TTCN_error("Matching an unbound component reference with a template.");
552 return match(other_value.component_value);
553 }
554
555 component COMPONENT_template::valueof() const
556 {
557 if (template_selection != SPECIFIC_VALUE || is_ifpresent)
558 TTCN_error("Performing a valueof or send operation on a non-specific "
559 "component reference template.");
560 return single_value;
561 }
562
563 void COMPONENT_template::set_type(template_sel template_type,
564 unsigned int list_length)
565 {
566 if (template_type != VALUE_LIST && template_type != COMPLEMENTED_LIST)
567 TTCN_error("Setting an invalid list type for a component reference "
568 "template.");
569 clean_up();
570 set_selection(template_type);
571 value_list.n_values = list_length;
572 value_list.list_value = new COMPONENT_template[list_length];
573 }
574
575 COMPONENT_template& COMPONENT_template::list_item(unsigned int list_index)
576 {
577 if (template_selection != VALUE_LIST &&
578 template_selection != COMPLEMENTED_LIST)
579 TTCN_error("Accessing a list element of a non-list component "
580 "reference template.");
581 if (list_index >= value_list.n_values)
582 TTCN_error("Index overflow in a component reference value list "
583 "template.");
584 return value_list.list_value[list_index];
585 }
586
587 void COMPONENT_template::log() const
588 {
589 switch (template_selection) {
590 case SPECIFIC_VALUE:
591 switch (single_value) {
592 case NULL_COMPREF:
593 TTCN_Logger::log_event_str("null");
594 break;
595 case MTC_COMPREF:
596 TTCN_Logger::log_event_str("mtc");
597 break;
598 case SYSTEM_COMPREF:
599 TTCN_Logger::log_event_str("system");
600 break;
601 default:
602 TTCN_Logger::log_event("%d", single_value);
603 break;
604 }
605 break;
606 case COMPLEMENTED_LIST:
607 TTCN_Logger::log_event_str("complement ");
608 // no break
609 case VALUE_LIST:
610 TTCN_Logger::log_char('(');
611 for (unsigned int i = 0; i < value_list.n_values; i++) {
612 if (i > 0) TTCN_Logger::log_event_str(", ");
613 value_list.list_value[i].log();
614 }
615 TTCN_Logger::log_char(')');
616 break;
617 default:
618 log_generic();
619 break;
620 }
621 log_ifpresent();
622 }
623
624 void COMPONENT_template::log_match(const COMPONENT& match_value,
625 boolean /* legacy */) const
626 {
627 if (TTCN_Logger::VERBOSITY_COMPACT == TTCN_Logger::get_matching_verbosity()
628 && TTCN_Logger::get_logmatch_buffer_len() != 0) {
629 TTCN_Logger::print_logmatch_buffer();
630 TTCN_Logger::log_event_str(" := ");
631 }
632 match_value.log();
633 TTCN_Logger::log_event_str(" with ");
634 log();
635 if (match(match_value)) TTCN_Logger::log_event_str(" matched");
636 else TTCN_Logger::log_event_str(" unmatched");
637 }
638
639 void COMPONENT_template::set_param(Module_Param& param) {
640 param.basic_check(Module_Param::BC_TEMPLATE, "component reference (integer or null) template");
641 Module_Param_Ptr mp = &param;
642 if (param.get_type() == Module_Param::MP_Reference) {
643 mp = param.get_referenced_param();
644 }
645 switch (mp->get_type()) {
646 case Module_Param::MP_Omit:
647 *this = OMIT_VALUE;
648 break;
649 case Module_Param::MP_Any:
650 *this = ANY_VALUE;
651 break;
652 case Module_Param::MP_AnyOrNone:
653 *this = ANY_OR_OMIT;
654 break;
655 case Module_Param::MP_List_Template:
656 case Module_Param::MP_ComplementList_Template: {
657 COMPONENT_template temp;
658 temp.set_type(mp->get_type() == Module_Param::MP_List_Template ?
659 VALUE_LIST : COMPLEMENTED_LIST, mp->get_size());
660 for (size_t i=0; i<mp->get_size(); i++) {
661 temp.list_item(i).set_param(*mp->get_elem(i));
662 }
663 *this = temp;
664 break; }
665 case Module_Param::MP_Integer:
666 *this = (component)mp->get_integer()->get_val();
667 break;
668 case Module_Param::MP_Ttcn_Null:
669 *this = NULL_COMPREF;
670 break;
671 case Module_Param::MP_Ttcn_mtc:
672 *this = MTC_COMPREF;
673 break;
674 case Module_Param::MP_Ttcn_system:
675 *this = SYSTEM_COMPREF;
676 break;
677 default:
678 param.type_error("component reference (integer or null) template");
679 }
680 is_ifpresent = param.get_ifpresent() || mp->get_ifpresent();
681 }
682
683 Module_Param* COMPONENT_template::get_param(Module_Param_Name& param_name) const
684 {
685 Module_Param* mp = NULL;
686 switch (template_selection) {
687 case UNINITIALIZED_TEMPLATE:
688 mp = new Module_Param_Unbound();
689 break;
690 case OMIT_VALUE:
691 mp = new Module_Param_Omit();
692 break;
693 case ANY_VALUE:
694 mp = new Module_Param_Any();
695 break;
696 case ANY_OR_OMIT:
697 mp = new Module_Param_AnyOrNone();
698 break;
699 case SPECIFIC_VALUE:
700 switch (single_value) {
701 case NULL_COMPREF:
702 mp = new Module_Param_Ttcn_Null();
703 break;
704 case MTC_COMPREF:
705 mp = new Module_Param_Ttcn_mtc();
706 break;
707 case SYSTEM_COMPREF:
708 mp = new Module_Param_Ttcn_system();
709 break;
710 default:
711 mp = new Module_Param_Integer(new int_val_t(single_value));
712 break;
713 }
714 break;
715 case VALUE_LIST:
716 case COMPLEMENTED_LIST: {
717 if (template_selection == VALUE_LIST) {
718 mp = new Module_Param_List_Template();
719 }
720 else {
721 mp = new Module_Param_ComplementList_Template();
722 }
723 for (size_t i = 0; i < value_list.n_values; ++i) {
724 mp->add_elem(value_list.list_value[i].get_param(param_name));
725 }
726 break; }
727 default:
728 break;
729 }
730 if (is_ifpresent) {
731 mp->set_ifpresent();
732 }
733 return mp;
734 }
735
736 void COMPONENT_template::encode_text(Text_Buf& text_buf) const
737 {
738 encode_text_base(text_buf);
739 switch (template_selection) {
740 case OMIT_VALUE:
741 case ANY_VALUE:
742 case ANY_OR_OMIT:
743 break;
744 case SPECIFIC_VALUE:
745 text_buf.push_int(single_value);
746 break;
747 case COMPLEMENTED_LIST:
748 case VALUE_LIST:
749 text_buf.push_int(value_list.n_values);
750 for (unsigned int i = 0; i < value_list.n_values; i++)
751 value_list.list_value[i].encode_text(text_buf);
752 break;
753 default:
754 TTCN_error("Text encoder: Encoding an uninitialized/unsupported "
755 "component reference template.");
756 }
757 }
758
759 void COMPONENT_template::decode_text(Text_Buf& text_buf)
760 {
761 clean_up();
762 decode_text_base(text_buf);
763 switch (template_selection) {
764 case OMIT_VALUE:
765 case ANY_VALUE:
766 case ANY_OR_OMIT:
767 break;
768 case SPECIFIC_VALUE:
769 single_value = (component)text_buf.pull_int().get_val();
770 break;
771 case COMPLEMENTED_LIST:
772 case VALUE_LIST:
773 value_list.n_values = text_buf.pull_int().get_val();
774 value_list.list_value = new COMPONENT_template[value_list.n_values];
775 for (unsigned int i = 0; i < value_list.n_values; i++)
776 value_list.list_value[i].decode_text(text_buf);
777 break;
778 default:
779 TTCN_error("Text decoder: An unknown/unsupported selection was "
780 "received for a component reference template.");
781 }
782 }
783
784 boolean COMPONENT_template::is_present(boolean legacy /* = FALSE */) const
785 {
786 if (template_selection==UNINITIALIZED_TEMPLATE) return FALSE;
787 return !match_omit(legacy);
788 }
789
790 boolean COMPONENT_template::match_omit(boolean legacy /* = FALSE */) const
791 {
792 if (is_ifpresent) return TRUE;
793 switch (template_selection) {
794 case OMIT_VALUE:
795 case ANY_OR_OMIT:
796 return TRUE;
797 case VALUE_LIST:
798 case COMPLEMENTED_LIST:
799 if (legacy) {
800 // legacy behavior: 'omit' can appear in the value/complement list
801 for (unsigned int i=0; i<value_list.n_values; i++)
802 if (value_list.list_value[i].match_omit())
803 return template_selection==VALUE_LIST;
804 return template_selection==COMPLEMENTED_LIST;
805 }
806 // else fall through
807 default:
808 return FALSE;
809 }
810 return FALSE;
811 }
812
813 #ifndef TITAN_RUNTIME_2
814 void COMPONENT_template::check_restriction(template_res t_res, const char* t_name,
815 boolean legacy /* = FALSE */) const
816 {
817 if (template_selection==UNINITIALIZED_TEMPLATE) return;
818 switch ((t_name&&(t_res==TR_VALUE))?TR_OMIT:t_res) {
819 case TR_VALUE:
820 if (!is_ifpresent && template_selection==SPECIFIC_VALUE) return;
821 break;
822 case TR_OMIT:
823 if (!is_ifpresent && (template_selection==OMIT_VALUE ||
824 template_selection==SPECIFIC_VALUE)) return;
825 break;
826 case TR_PRESENT:
827 if (!match_omit(legacy)) return;
828 break;
829 default:
830 return;
831 }
832 TTCN_error("Restriction `%s' on template of type %s violated.",
833 get_res_name(t_res), t_name ? t_name : "component reference");
834 }
835 #endif
836
837 const COMPONENT_template any_compref_value(ANY_VALUE);
838 const COMPONENT_template& any_compref = any_compref_value;
This page took 0.05918 seconds and 5 git commands to generate.