clang specific define in Runtime.cc
[deliverable/titan.core.git] / core / Verdicttype.cc
1 /******************************************************************************
2 * Copyright (c) 2000-2016 Ericsson Telecom AB
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/epl-v10.html
7 *
8 * Contributors:
9 * Baji, Laszlo
10 * Balasko, Jeno
11 * Baranyi, Botond
12 * Beres, Szabolcs
13 * Delic, Adam
14 * Forstner, Matyas
15 * Kovacs, Ferenc
16 * Raduly, Csaba
17 * Szabados, Kristof
18 * Szabo, Bence Janos
19 * Szabo, Janos Zoltan – initial implementation
20 * Tatarka, Gabor
21 *
22 ******************************************************************************/
23 #include "Verdicttype.hh"
24
25 #include "Param_Types.hh"
26 #include "Error.hh"
27 #include "Logger.hh"
28 #include "Textbuf.hh"
29
30 #include "../common/dbgnew.hh"
31
32 #define UNBOUND_VERDICT ((verdicttype)(ERROR + 1))
33 #define IS_VALID(verdict_value) (verdict_value >= NONE && verdict_value <= ERROR)
34
35 const char * const verdict_name[] = { "none", "pass", "inconc", "fail", "error" };
36
37 VERDICTTYPE::VERDICTTYPE()
38 {
39 verdict_value = UNBOUND_VERDICT;
40 }
41
42 VERDICTTYPE::VERDICTTYPE(verdicttype other_value)
43 {
44 if (!IS_VALID(other_value)) TTCN_error("Initializing a verdict variable "
45 "with an invalid value (%d).", other_value);
46 verdict_value = other_value;
47 }
48
49 VERDICTTYPE::VERDICTTYPE(const VERDICTTYPE& other_value)
50 : Base_Type(other_value)
51 {
52 if (!other_value.is_bound()) TTCN_error("Copying an unbound verdict value.");
53 verdict_value = other_value.verdict_value;
54 }
55
56 VERDICTTYPE& VERDICTTYPE::operator=(verdicttype other_value)
57 {
58 if (!IS_VALID(other_value))
59 TTCN_error("Assignment of an invalid verdict value (%d).", other_value);
60 verdict_value = other_value;
61 return *this;
62 }
63
64 VERDICTTYPE& VERDICTTYPE::operator=(const VERDICTTYPE& other_value)
65 {
66 if (!other_value.is_bound())
67 TTCN_error("Assignment of an unbound verdict value.");
68 verdict_value = other_value.verdict_value;
69 return *this;
70 }
71
72 boolean VERDICTTYPE::operator==(verdicttype other_value) const
73 {
74 if (!is_bound()) TTCN_error("The left operand of comparison is an unbound "
75 "verdict value.");
76 if (!IS_VALID(other_value)) TTCN_error("The right operand of comparison is "
77 "an invalid verdict value (%d).", other_value);
78 return verdict_value == other_value;
79 }
80
81 boolean VERDICTTYPE::operator==(const VERDICTTYPE& other_value) const
82 {
83 if (!is_bound()) TTCN_error("The left operand of comparison is an unbound "
84 "verdict value.");
85 if (!other_value.is_bound()) TTCN_error("The right operand of comparison is "
86 "an unbound verdict value.");
87 return verdict_value == other_value.verdict_value;
88 }
89
90 VERDICTTYPE::operator verdicttype() const
91 {
92 if (!is_bound())
93 TTCN_error("Using the value of an unbound verdict variable.");
94 return verdict_value;
95 }
96
97 void VERDICTTYPE::clean_up()
98 {
99 verdict_value = UNBOUND_VERDICT;
100 }
101
102 void VERDICTTYPE::log() const
103 {
104 if (IS_VALID(verdict_value))
105 TTCN_Logger::log_event_str(verdict_name[verdict_value]);
106 else if (verdict_value == UNBOUND_VERDICT)
107 TTCN_Logger::log_event_unbound();
108 else TTCN_Logger::log_event("<invalid verdict value: %d>", verdict_value);
109 }
110
111 void VERDICTTYPE::set_param(Module_Param& param) {
112 param.basic_check(Module_Param::BC_VALUE, "verdict value");
113 Module_Param_Ptr mp = &param;
114 if (param.get_type() == Module_Param::MP_Reference) {
115 mp = param.get_referenced_param();
116 }
117 if (mp->get_type()!=Module_Param::MP_Verdict) param.type_error("verdict value");
118 const verdicttype verdict = mp->get_verdict();
119 if (!IS_VALID(verdict)) param.error("Internal error: invalid verdict value (%d).", verdict);
120 verdict_value = verdict;
121 }
122
123 Module_Param* VERDICTTYPE::get_param(Module_Param_Name& /* param_name */) const
124 {
125 if (!is_bound()) {
126 return new Module_Param_Unbound();
127 }
128 return new Module_Param_Verdict(verdict_value);
129 }
130
131 void VERDICTTYPE::encode_text(Text_Buf& text_buf) const
132 {
133 if (!is_bound())
134 TTCN_error("Text encoder: Encoding an unbound verdict value.");
135 text_buf.push_int(verdict_value);
136 }
137
138 void VERDICTTYPE::decode_text(Text_Buf& text_buf)
139 {
140 int received_value = text_buf.pull_int().get_val();
141 if (!IS_VALID(received_value)) TTCN_error("Text decoder: Invalid verdict "
142 "value (%d) was received.", received_value);
143 verdict_value = (verdicttype)received_value;
144 }
145
146 void VERDICTTYPE::encode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf,
147 TTCN_EncDec::coding_t p_coding, ...) const
148 {
149 va_list pvar;
150 va_start(pvar, p_coding);
151 switch(p_coding) {
152 #if 0
153 case TTCN_EncDec::CT_BER: {
154 TTCN_EncDec_ErrorContext ec("While BER-encoding type '%s': ", p_td.name);
155 unsigned BER_coding=va_arg(pvar, unsigned);
156 BER_encode_chk_coding(BER_coding);
157 ASN_BER_TLV_t *tlv=BER_encode_TLV(p_td, BER_coding);
158 tlv->put_in_buffer(p_buf);
159 ASN_BER_TLV_t::destruct(tlv);
160 break;}
161 case TTCN_EncDec::CT_RAW: {
162 TTCN_EncDec_ErrorContext ec("While RAW-encoding type '%s': ", p_td.name);
163 if(!p_td.raw)
164 TTCN_EncDec_ErrorContext::error_internal
165 ("No RAW descriptor available for type '%s'.", p_td.name);
166 RAW_enc_tr_pos rp;
167 rp.level=0;
168 rp.pos=NULL;
169 RAW_enc_tree root(TRUE,NULL,&rp,1,p_td.raw);
170 RAW_encode(p_td, root);
171 root.put_to_buf(p_buf);
172 break;}
173 case TTCN_EncDec::CT_TEXT: {
174 TTCN_EncDec_ErrorContext ec("While TEXT-encoding type '%s': ", p_td.name);
175 if(!p_td.text)
176 TTCN_EncDec_ErrorContext::error_internal
177 ("No TEXT descriptor available for type '%s'.", p_td.name);
178 TEXT_encode(p_td,p_buf);
179 break;}
180 #endif
181 case TTCN_EncDec::CT_XER: {
182 TTCN_EncDec_ErrorContext ec("While XER-encoding type '%s': ", p_td.name);
183 unsigned XER_coding=va_arg(pvar, unsigned);
184 XER_encode(*p_td.xer, p_buf, XER_coding, 0, 0);
185 break;}
186 case TTCN_EncDec::CT_JSON: {
187 TTCN_EncDec_ErrorContext ec("While JSON-encoding type '%s': ", p_td.name);
188 if(!p_td.json)
189 TTCN_EncDec_ErrorContext::error_internal
190 ("No JSON descriptor available for type '%s'.", p_td.name);
191 JSON_Tokenizer tok(va_arg(pvar, int) != 0);
192 JSON_encode(p_td, tok);
193 p_buf.put_s(tok.get_buffer_length(), (const unsigned char*)tok.get_buffer());
194 break;}
195 default:
196 TTCN_error("Unknown coding method requested to encode type '%s'",
197 p_td.name);
198 }
199 va_end(pvar);
200 }
201
202 void VERDICTTYPE::decode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf,
203 TTCN_EncDec::coding_t p_coding, ...)
204 {
205 va_list pvar;
206 va_start(pvar, p_coding);
207 switch(p_coding) {
208 #if 0
209 case TTCN_EncDec::CT_RAW: {
210 TTCN_EncDec_ErrorContext ec("While RAW-decoding type '%s': ", p_td.name);
211 if(!p_td.raw)
212 TTCN_EncDec_ErrorContext::error_internal
213 ("No RAW descriptor available for type '%s'.", p_td.name);
214 raw_order_t order;
215 switch(p_td.raw->top_bit_order){
216 case TOP_BIT_LEFT:
217 order=ORDER_LSB;
218 break;
219 case TOP_BIT_RIGHT:
220 default:
221 order=ORDER_MSB;
222 }
223 if(RAW_decode(p_td, p_buf, p_buf.get_len()*8, order)<0)
224 ec.error(TTCN_EncDec::ET_INCOMPL_MSG,
225 "Can not decode type '%s', because invalid or incomplete"
226 " message was received"
227 , p_td.name);
228 break;}
229 case TTCN_EncDec::CT_TEXT: {
230 Limit_Token_List limit;
231 TTCN_EncDec_ErrorContext ec("While TEXT-decoding type '%s': ", p_td.name);
232 if(!p_td.text)
233 TTCN_EncDec_ErrorContext::error_internal
234 ("No TEXT descriptor available for type '%s'.", p_td.name);
235 const unsigned char *b=p_buf.get_data();
236 if(b[p_buf.get_len()-1]!='\0'){
237 p_buf.set_pos(p_buf.get_len());
238 p_buf.put_zero(8,ORDER_LSB);
239 p_buf.rewind();
240 }
241 if(TEXT_decode(p_td,p_buf,limit)<0)
242 ec.error(TTCN_EncDec::ET_INCOMPL_MSG,
243 "Can not decode type '%s', because invalid or incomplete"
244 " message was received"
245 , p_td.name);
246 break;}
247 #endif
248 case TTCN_EncDec::CT_XER: {
249 TTCN_EncDec_ErrorContext ec("While XER-decoding type '%s': ", p_td.name);
250 unsigned XER_coding=va_arg(pvar, unsigned);
251 XmlReaderWrap reader(p_buf);
252 for (int success = reader.Read(); success==1; success=reader.Read()) {
253 int type = reader.NodeType();
254 if (type==XML_READER_TYPE_ELEMENT)
255 break;
256 }
257 XER_decode(*p_td.xer, reader, XER_coding, XER_NONE, 0);
258 size_t bytes = reader.ByteConsumed();
259 p_buf.set_pos(bytes);
260 break;}
261 case TTCN_EncDec::CT_JSON: {
262 TTCN_EncDec_ErrorContext ec("While JSON-decoding type '%s': ", p_td.name);
263 if(!p_td.json)
264 TTCN_EncDec_ErrorContext::error_internal
265 ("No JSON descriptor available for type '%s'.", p_td.name);
266 JSON_Tokenizer tok((const char*)p_buf.get_data(), p_buf.get_len());
267 if(JSON_decode(p_td, tok, false)<0)
268 ec.error(TTCN_EncDec::ET_INCOMPL_MSG,
269 "Can not decode type '%s', because invalid or incomplete"
270 " message was received"
271 , p_td.name);
272 p_buf.set_pos(tok.get_buf_pos());
273 break;}
274 default:
275 TTCN_error("Unknown coding method requested to decode type '%s'",
276 p_td.name);
277 }
278 va_end(pvar);
279 }
280
281
282 int VERDICTTYPE::XER_encode(const XERdescriptor_t& p_td, TTCN_Buffer& p_buf,
283 unsigned int p_flavor, int p_indent, embed_values_enc_struct_t*) const
284 {
285 int encoded_length=(int)p_buf.get_len();
286 //const boolean e_xer = is_exer(p_flavor);
287 p_flavor |= (SIMPLE_TYPE | BXER_EMPTY_ELEM);
288 if (begin_xml(p_td, p_buf, p_flavor, p_indent, false) == -1) --encoded_length;
289 //if (!e_xer) p_buf.put_c('<');
290 {
291 const char * enumval = verdict_name[verdict_value];
292 p_buf.put_s(strlen(enumval), (const unsigned char*)enumval);
293 }
294 //if (!e_xer) p_buf.put_s(2, (const unsigned char*)"/>");
295 end_xml(p_td, p_buf, p_flavor, p_indent, false);
296 return (int)p_buf.get_len() - encoded_length;
297 }
298
299 verdicttype VERDICTTYPE::str_to_verdict(const char *v, boolean silent)
300 {
301 for (int i = NONE; i <= ERROR; ++i) {
302 if (0 == strcmp(v, verdict_name[i])) {
303 return (verdicttype)i;
304 }
305 }
306
307 if (!silent) {
308 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_INVAL_MSG,
309 "Invalid value for verdicttype: '%s'", v);
310 }
311 return UNBOUND_VERDICT;
312 }
313
314 int VERDICTTYPE::XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& p_reader,
315 unsigned int p_flavor, unsigned int /*flavor2*/, embed_values_dec_struct_t*)
316 {
317 int rd_ok = 1, type;
318 const int e_xer = is_exer(p_flavor);
319 const boolean name_tag = !((!e_xer && is_record_of(p_flavor)) || (e_xer && ((p_td.xer_bits & UNTAGGED) ||(is_record_of(p_flavor) && is_exerlist(p_flavor)))));
320 if (e_xer && ((p_td.xer_bits & XER_ATTRIBUTE) || is_exerlist(p_flavor))) {
321 if ((p_td.xer_bits & XER_ATTRIBUTE)) verify_name(p_reader, p_td, e_xer);
322 const char * value = (const char *)p_reader.Value();
323 if (value) {
324 verdict_value = str_to_verdict(value, (p_flavor & EXIT_ON_ERROR) ? true : false);
325 }
326 }
327 else {
328 if (name_tag) for (; rd_ok == 1; rd_ok = p_reader.Read()) {
329 type = p_reader.NodeType();
330 if (XML_READER_TYPE_ELEMENT == type) {
331 rd_ok = p_reader.Read();
332 break;
333 }
334 }
335 for (; rd_ok == 1; rd_ok = p_reader.Read()) {
336 type = p_reader.NodeType();
337 if (!e_xer && XML_READER_TYPE_ELEMENT == type) break;
338 if (XML_READER_TYPE_TEXT == type) break;
339 }
340 const char *local_name = /*e_xer ?*/ (const char *)p_reader.Value() /*: (const char *)p_reader.Name()*/;
341 if (!local_name) ; else {
342 for (; '\t'==*local_name || '\n'==*local_name; ++local_name) ;
343 verdict_value = str_to_verdict(local_name, (p_flavor & EXIT_ON_ERROR) ? true : false);
344 }
345 if (name_tag)
346 for (rd_ok = p_reader.Read(); rd_ok == 1; rd_ok = p_reader.Read()) {
347 type = p_reader.NodeType();
348 if (XML_READER_TYPE_END_ELEMENT == type) {
349 p_reader.Read();
350 break;
351 }
352 }
353 else p_reader.Read();
354 }
355 int decoded_length = 0;
356 return decoded_length;
357 }
358
359 int VERDICTTYPE::JSON_encode(const TTCN_Typedescriptor_t&, JSON_Tokenizer& p_tok) const
360 {
361 if (!is_bound()) {
362 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND,
363 "Encoding an unbound verdicttype value.");
364 return -1;
365 }
366
367 char* tmp_str = mprintf("\"%s\"", verdict_name[verdict_value]);
368 int enc_len = p_tok.put_next_token(JSON_TOKEN_STRING, tmp_str);
369 Free(tmp_str);
370 return enc_len;
371 }
372
373 int VERDICTTYPE::JSON_decode(const TTCN_Typedescriptor_t& p_td, JSON_Tokenizer& p_tok, boolean p_silent)
374 {
375 json_token_t token = JSON_TOKEN_NONE;
376 char* value = 0;
377 size_t value_len = 0;
378 int dec_len = 0;
379 boolean use_default = p_td.json->default_value && 0 == p_tok.get_buffer_length();
380 if (use_default) {
381 // No JSON data in the buffer -> use default value
382 value = (char*)p_td.json->default_value;
383 value_len = strlen(value);
384 } else {
385 dec_len = p_tok.get_next_token(&token, &value, &value_len);
386 }
387 boolean error = true;
388 if (JSON_TOKEN_ERROR == token) {
389 JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_BAD_TOKEN_ERROR, "");
390 dec_len = JSON_ERROR_FATAL;
391 }
392 else if (JSON_TOKEN_STRING == token || use_default) {
393 if (use_default || (value[0] == '\"' && value[value_len - 1] == '\"')) {
394 if (!use_default) {
395 // The default value doesn't have quotes around it
396 value_len -= 2;
397 ++value;
398 }
399 for (int i = NONE; i <= ERROR; ++i) {
400 if (0 == strncmp(value, verdict_name[i], value_len)) {
401 verdict_value = (verdicttype)i;
402 error = false;
403 break;
404 }
405 }
406 }
407 } else {
408 error = false;
409 verdict_value = UNBOUND_VERDICT;
410 dec_len = JSON_ERROR_INVALID_TOKEN;
411 }
412 if (error) {
413 JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_FORMAT_ERROR, "string", "verdicttype");
414 verdict_value = UNBOUND_VERDICT;
415 dec_len = JSON_ERROR_FATAL;
416 }
417 return dec_len;
418 }
419
420
421 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
422
423 boolean operator==(verdicttype par_value, const VERDICTTYPE& other_value)
424 {
425 if (!IS_VALID(par_value)) TTCN_error("The left operand of comparison is "
426 "an invalid verdict value (%d).", par_value);
427 if (!other_value.is_bound()) TTCN_error("The right operand of comparison "
428 "is an unbound verdict value.");
429 return par_value == other_value.verdict_value;
430 }
431
432 void VERDICTTYPE_template::clean_up()
433 {
434 if (template_selection == VALUE_LIST ||
435 template_selection == COMPLEMENTED_LIST)
436 delete [] value_list.list_value;
437 template_selection = UNINITIALIZED_TEMPLATE;
438 }
439
440 void VERDICTTYPE_template::copy_value(const VERDICTTYPE& other_value)
441 {
442 if (!other_value.is_bound())
443 TTCN_error("Creating a template from an unbound verdict value.");
444 single_value = other_value.verdict_value;
445 set_selection(SPECIFIC_VALUE);
446 }
447
448 void VERDICTTYPE_template::copy_template
449 (const VERDICTTYPE_template& other_value)
450 {
451 switch (other_value.template_selection) {
452 case SPECIFIC_VALUE:
453 single_value = other_value.single_value;
454 break;
455 case OMIT_VALUE:
456 case ANY_VALUE:
457 case ANY_OR_OMIT:
458 break;
459 case VALUE_LIST:
460 case COMPLEMENTED_LIST:
461 value_list.n_values = other_value.value_list.n_values;
462 value_list.list_value = new VERDICTTYPE_template[value_list.n_values];
463 for (unsigned int i = 0; i < value_list.n_values; i++)
464 value_list.list_value[i].copy_template(
465 other_value.value_list.list_value[i]);
466 break;
467 default:
468 TTCN_error("Copying an uninitialized/unsupported verdict template.");
469 }
470 set_selection(other_value);
471 }
472
473 VERDICTTYPE_template::VERDICTTYPE_template()
474 {
475 }
476
477 VERDICTTYPE_template::VERDICTTYPE_template(template_sel other_value)
478 : Base_Template(other_value)
479 {
480 check_single_selection(other_value);
481 }
482
483 VERDICTTYPE_template::VERDICTTYPE_template(verdicttype other_value)
484 : Base_Template(SPECIFIC_VALUE)
485 {
486 if (!IS_VALID(other_value)) TTCN_error("Creating a template from an "
487 "invalid verdict value (%d).", other_value);
488 single_value = other_value;
489 }
490
491 VERDICTTYPE_template::VERDICTTYPE_template(const VERDICTTYPE& other_value)
492 {
493 copy_value(other_value);
494 }
495
496 VERDICTTYPE_template::VERDICTTYPE_template
497 (const OPTIONAL<VERDICTTYPE>& other_value)
498 {
499 switch (other_value.get_selection()) {
500 case OPTIONAL_PRESENT:
501 copy_value((const VERDICTTYPE&)other_value);
502 break;
503 case OPTIONAL_OMIT:
504 set_selection(OMIT_VALUE);
505 break;
506 default:
507 TTCN_error("Creating a verdict template from an unbound optional field.");
508 }
509 }
510
511 VERDICTTYPE_template::VERDICTTYPE_template
512 (const VERDICTTYPE_template& other_value)
513 : Base_Template()
514 {
515 copy_template(other_value);
516 }
517
518 VERDICTTYPE_template::~VERDICTTYPE_template()
519 {
520 clean_up();
521 }
522
523 VERDICTTYPE_template& VERDICTTYPE_template::operator=(template_sel other_value)
524 {
525 check_single_selection(other_value);
526 clean_up();
527 set_selection(other_value);
528 return *this;
529 }
530
531 VERDICTTYPE_template& VERDICTTYPE_template::operator=(verdicttype other_value)
532 {
533 if (!IS_VALID(other_value)) TTCN_error("Assignment of an invalid verdict "
534 "value (%d) to a template.", other_value);
535 clean_up();
536 set_selection(SPECIFIC_VALUE);
537 single_value = other_value;
538 return *this;
539 }
540
541 VERDICTTYPE_template& VERDICTTYPE_template::operator=
542 (const VERDICTTYPE& other_value)
543 {
544 clean_up();
545 copy_value(other_value);
546 return *this;
547 }
548
549 VERDICTTYPE_template& VERDICTTYPE_template::operator=
550 (const OPTIONAL<VERDICTTYPE>& other_value)
551 {
552 clean_up();
553 switch (other_value.get_selection()) {
554 case OPTIONAL_PRESENT:
555 copy_value((const VERDICTTYPE&)other_value);
556 break;
557 case OPTIONAL_OMIT:
558 set_selection(OMIT_VALUE);
559 break;
560 default:
561 TTCN_error("Assignment of an unbound optional field to a verdict "
562 "template.");
563 }
564 return *this;
565 }
566
567 VERDICTTYPE_template& VERDICTTYPE_template::operator=
568 (const VERDICTTYPE_template& other_value)
569 {
570 if (&other_value != this) {
571 clean_up();
572 copy_template(other_value);
573 }
574 return *this;
575 }
576
577 boolean VERDICTTYPE_template::match(verdicttype other_value,
578 boolean /* legacy */) const
579 {
580 if (!IS_VALID(other_value)) TTCN_error("Matching a verdict template with "
581 "an invalid value (%d).", other_value);
582 switch (template_selection) {
583 case SPECIFIC_VALUE:
584 return single_value == other_value;
585 case OMIT_VALUE:
586 return FALSE;
587 case ANY_VALUE:
588 case ANY_OR_OMIT:
589 return TRUE;
590 case VALUE_LIST:
591 case COMPLEMENTED_LIST:
592 for (unsigned int i = 0; i < value_list.n_values; i++)
593 if (value_list.list_value[i].match(other_value))
594 return template_selection == VALUE_LIST;
595 return template_selection == COMPLEMENTED_LIST;
596 default:
597 TTCN_error("Matching with an uninitialized/unsupported verdict template.");
598 }
599 return FALSE;
600 }
601
602 boolean VERDICTTYPE_template::match(const VERDICTTYPE& other_value,
603 boolean /* legacy */) const
604 {
605 if (!other_value.is_bound()) return FALSE;
606 return match(other_value.verdict_value);
607 }
608
609 verdicttype VERDICTTYPE_template::valueof() const
610 {
611 if (template_selection != SPECIFIC_VALUE || is_ifpresent)
612 TTCN_error("Performing a valueof "
613 "or send operation on a non-specific verdict template.");
614 return single_value;
615 }
616
617 void VERDICTTYPE_template::set_type(template_sel template_type,
618 unsigned int list_length)
619 {
620 if (template_type != VALUE_LIST && template_type != COMPLEMENTED_LIST)
621 TTCN_error("Internal error: Setting an invalid list type for a verdict "
622 "template.");
623 clean_up();
624 set_selection(template_type);
625 value_list.n_values = list_length;
626 value_list.list_value = new VERDICTTYPE_template[list_length];
627 }
628
629 VERDICTTYPE_template& VERDICTTYPE_template::list_item(unsigned int list_index)
630 {
631 if (template_selection != VALUE_LIST &&
632 template_selection != COMPLEMENTED_LIST)
633 TTCN_error("Internal error: Accessing a list element of a non-list "
634 "verdict template.");
635 if (list_index >= value_list.n_values)
636 TTCN_error("Internal error: Index overflow in a verdict value list "
637 "template.");
638 return value_list.list_value[list_index];
639 }
640
641 void VERDICTTYPE_template::log() const
642 {
643 switch (template_selection) {
644 case SPECIFIC_VALUE:
645 if (IS_VALID(single_value))
646 TTCN_Logger::log_event("%s", verdict_name[single_value]);
647 else TTCN_Logger::log_event("<unknown verdict value: %d>", single_value);
648 break;
649 case COMPLEMENTED_LIST:
650 TTCN_Logger::log_event_str("complement ");
651 // no break
652 case VALUE_LIST:
653 TTCN_Logger::log_char('(');
654 for (unsigned int i = 0; i < value_list.n_values; i++) {
655 if (i > 0) TTCN_Logger::log_event_str(", ");
656 value_list.list_value[i].log();
657 }
658 TTCN_Logger::log_char(')');
659 break;
660 default:
661 log_generic();
662 break;
663 }
664 log_ifpresent();
665 }
666
667 void VERDICTTYPE_template::log_match(const VERDICTTYPE& match_value,
668 boolean /* legacy */) const
669 {
670 if (TTCN_Logger::VERBOSITY_COMPACT == TTCN_Logger::get_matching_verbosity()
671 && TTCN_Logger::get_logmatch_buffer_len() != 0) {
672 TTCN_Logger::print_logmatch_buffer();
673 TTCN_Logger::log_event_str(" := ");
674 }
675 match_value.log();
676 TTCN_Logger::log_event_str(" with ");
677 log();
678 if (match(match_value)) TTCN_Logger::log_event_str(" matched");
679 else TTCN_Logger::log_event_str(" unmatched");
680 }
681
682 void VERDICTTYPE_template::set_param(Module_Param& param) {
683 param.basic_check(Module_Param::BC_TEMPLATE, "verdict template");
684 Module_Param_Ptr mp = &param;
685 if (param.get_type() == Module_Param::MP_Reference) {
686 mp = param.get_referenced_param();
687 }
688 switch (mp->get_type()) {
689 case Module_Param::MP_Omit:
690 *this = OMIT_VALUE;
691 break;
692 case Module_Param::MP_Any:
693 *this = ANY_VALUE;
694 break;
695 case Module_Param::MP_AnyOrNone:
696 *this = ANY_OR_OMIT;
697 break;
698 case Module_Param::MP_List_Template:
699 case Module_Param::MP_ComplementList_Template: {
700 VERDICTTYPE_template temp;
701 temp.set_type(mp->get_type() == Module_Param::MP_List_Template ?
702 VALUE_LIST : COMPLEMENTED_LIST, mp->get_size());
703 for (size_t i=0; i<mp->get_size(); i++) {
704 temp.list_item(i).set_param(*mp->get_elem(i));
705 }
706 *this = temp;
707 break; }
708 case Module_Param::MP_Verdict:
709 *this = mp->get_verdict();
710 break;
711 default:
712 param.type_error("verdict template");
713 }
714 is_ifpresent = param.get_ifpresent() || mp->get_ifpresent();
715 }
716
717 Module_Param* VERDICTTYPE_template::get_param(Module_Param_Name& param_name) const
718 {
719 Module_Param* mp = NULL;
720 switch (template_selection) {
721 case UNINITIALIZED_TEMPLATE:
722 mp = new Module_Param_Unbound();
723 break;
724 case OMIT_VALUE:
725 mp = new Module_Param_Omit();
726 break;
727 case ANY_VALUE:
728 mp = new Module_Param_Any();
729 break;
730 case ANY_OR_OMIT:
731 mp = new Module_Param_AnyOrNone();
732 break;
733 case SPECIFIC_VALUE:
734 mp = new Module_Param_Verdict(single_value);
735 break;
736 case VALUE_LIST:
737 case COMPLEMENTED_LIST: {
738 if (template_selection == VALUE_LIST) {
739 mp = new Module_Param_List_Template();
740 }
741 else {
742 mp = new Module_Param_ComplementList_Template();
743 }
744 for (size_t i = 0; i < value_list.n_values; ++i) {
745 mp->add_elem(value_list.list_value[i].get_param(param_name));
746 }
747 break; }
748 default:
749 break;
750 }
751 if (is_ifpresent) {
752 mp->set_ifpresent();
753 }
754 return mp;
755 }
756
757 void VERDICTTYPE_template::encode_text(Text_Buf& text_buf) const
758 {
759 encode_text_base(text_buf);
760 switch (template_selection) {
761 case OMIT_VALUE:
762 case ANY_VALUE:
763 case ANY_OR_OMIT:
764 break;
765 case SPECIFIC_VALUE:
766 text_buf.push_int(single_value);
767 break;
768 case VALUE_LIST:
769 case COMPLEMENTED_LIST:
770 text_buf.push_int(value_list.n_values);
771 for (unsigned int i = 0; i < value_list.n_values; i++)
772 value_list.list_value[i].encode_text(text_buf);
773 break;
774 default:
775 TTCN_error("Text encoder: Encoding an undefined/unsupported verdict "
776 "template.");
777 }
778 }
779
780 void VERDICTTYPE_template::decode_text(Text_Buf& text_buf)
781 {
782 clean_up();
783 decode_text_base(text_buf);
784 switch (template_selection) {
785 case OMIT_VALUE:
786 case ANY_VALUE:
787 case ANY_OR_OMIT:
788 break;
789 case SPECIFIC_VALUE: {
790 int received_value = text_buf.pull_int().get_val();
791 if (!IS_VALID(received_value)) TTCN_error("Text decoder: Invalid "
792 "verdict value (%d) was received for a template.", received_value);
793 single_value = (verdicttype)received_value;
794 break; }
795 case VALUE_LIST:
796 case COMPLEMENTED_LIST:
797 value_list.n_values = text_buf.pull_int().get_val();
798 value_list.list_value = new VERDICTTYPE_template[value_list.n_values];
799 for (unsigned int i = 0; i < value_list.n_values; i++)
800 value_list.list_value[i].decode_text(text_buf);
801 break;
802 default:
803 TTCN_error("Text decoder: An unknown/unsupported selection was received "
804 "for a verdict template.");
805 }
806 }
807
808 boolean VERDICTTYPE_template::is_present(boolean legacy /* = FALSE */) const
809 {
810 if (template_selection==UNINITIALIZED_TEMPLATE) return FALSE;
811 return !match_omit(legacy);
812 }
813
814 boolean VERDICTTYPE_template::match_omit(boolean legacy /* = FALSE */) const
815 {
816 if (is_ifpresent) return TRUE;
817 switch (template_selection) {
818 case OMIT_VALUE:
819 case ANY_OR_OMIT:
820 return TRUE;
821 case VALUE_LIST:
822 case COMPLEMENTED_LIST:
823 if (legacy) {
824 // legacy behavior: 'omit' can appear in the value/complement list
825 for (unsigned int i=0; i<value_list.n_values; i++)
826 if (value_list.list_value[i].match_omit())
827 return template_selection==VALUE_LIST;
828 return template_selection==COMPLEMENTED_LIST;
829 }
830 // else fall through
831 default:
832 return FALSE;
833 }
834 return FALSE;
835 }
836
837 #ifndef TITAN_RUNTIME_2
838 void VERDICTTYPE_template::check_restriction(template_res t_res, const char* t_name,
839 boolean legacy /* = FALSE */) const
840 {
841 if (template_selection==UNINITIALIZED_TEMPLATE) return;
842 switch ((t_name&&(t_res==TR_VALUE))?TR_OMIT:t_res) {
843 case TR_VALUE:
844 if (!is_ifpresent && template_selection==SPECIFIC_VALUE) return;
845 break;
846 case TR_OMIT:
847 if (!is_ifpresent && (template_selection==OMIT_VALUE ||
848 template_selection==SPECIFIC_VALUE)) return;
849 break;
850 case TR_PRESENT:
851 if (!match_omit(legacy)) return;
852 break;
853 default:
854 return;
855 }
856 TTCN_error("Restriction `%s' on template of type %s violated.",
857 get_res_name(t_res), t_name ? t_name : "verdict");
858 }
859 #endif
This page took 0.04963 seconds and 5 git commands to generate.