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