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