Sync with 5.2.0
[deliverable/titan.core.git] / core / Boolean.cc
1 ///////////////////////////////////////////////////////////////////////////////
2 // Copyright (c) 2000-2014 Ericsson Telecom AB
3 // All rights reserved. This program and the accompanying materials
4 // are made available under the terms of the Eclipse Public License v1.0
5 // which accompanies this distribution, and is available at
6 // http://www.eclipse.org/legal/epl-v10.html
7 ///////////////////////////////////////////////////////////////////////////////
8 #include <string.h>
9
10 #include "Boolean.hh"
11 #include "../common/memory.h"
12 #include "Parameters.h"
13 #include "Param_Types.hh"
14 #include "Error.hh"
15 #include "Logger.hh"
16 #include "Encdec.hh"
17 #include "RAW.hh"
18 #include "BER.hh"
19 #include "TEXT.hh"
20 #include "Charstring.hh"
21 #include "XmlReader.hh"
22
23 static const Token_Match boolean_true_match("^(true).*$",TRUE);
24 static const Token_Match boolean_false_match("^(false).*$",TRUE);
25
26 BOOLEAN::BOOLEAN()
27 {
28 bound_flag = FALSE;
29 }
30
31 BOOLEAN::BOOLEAN(boolean other_value)
32 {
33 bound_flag = TRUE;
34 boolean_value = other_value;
35 }
36
37 BOOLEAN::BOOLEAN(const BOOLEAN& other_value)
38 : Base_Type(other_value)
39 {
40 other_value.must_bound("Copying an unbound boolean value.");
41 bound_flag = TRUE;
42 boolean_value = other_value.boolean_value;
43 }
44
45 BOOLEAN& BOOLEAN::operator=(boolean other_value)
46 {
47 bound_flag = TRUE;
48 boolean_value = other_value;
49 return *this;
50 }
51
52 BOOLEAN& BOOLEAN::operator=(const BOOLEAN& other_value)
53 {
54 other_value.must_bound("Assignment of an unbound boolean value.");
55 bound_flag = TRUE;
56 boolean_value = other_value.boolean_value;
57 return *this;
58 }
59
60 boolean BOOLEAN::operator!() const
61 {
62 must_bound("The operand of not operator is an unbound boolean value.");
63 return !boolean_value;
64 }
65
66 boolean BOOLEAN::operator&&(boolean other_value) const
67 {
68 must_bound("The left operand of and operator is an unbound boolean value.");
69 return boolean_value && other_value;
70 }
71
72 boolean BOOLEAN::operator&&(const BOOLEAN& other_value) const
73 {
74 must_bound("The left operand of and operator is an unbound boolean value.");
75 if (!boolean_value) return FALSE;
76 other_value.must_bound("The right operand of and operator is an unbound "
77 "boolean value.");
78 return other_value.boolean_value;
79 }
80
81 boolean BOOLEAN::operator^(boolean other_value) const
82 {
83 must_bound("The left operand of xor operator is an unbound boolean value.");
84 return boolean_value != other_value;
85 }
86
87 boolean BOOLEAN::operator^(const BOOLEAN& other_value) const
88 {
89 must_bound("The left operand of xor operator is an unbound boolean value.");
90 other_value.must_bound("The right operand of xor operator is an unbound "
91 "boolean value.");
92 return boolean_value != other_value.boolean_value;
93 }
94
95 boolean BOOLEAN::operator||(boolean other_value) const
96 {
97 must_bound("The left operand of or operator is an unbound boolean value.");
98 return boolean_value || other_value;
99 }
100
101 boolean BOOLEAN::operator||(const BOOLEAN& other_value) const
102 {
103 must_bound("The left operand of or operator is an unbound boolean value.");
104 if (boolean_value) return TRUE;
105 other_value.must_bound("The right operand of or operator is an unbound "
106 "boolean value.");
107 return other_value.boolean_value;
108 }
109
110 boolean BOOLEAN::operator==(boolean other_value) const
111 {
112 must_bound("The left operand of comparison is an unbound boolean value.");
113 return boolean_value == other_value;
114 }
115
116 boolean BOOLEAN::operator==(const BOOLEAN& other_value) const
117 {
118 must_bound("The left operand of comparison is an unbound boolean value.");
119 other_value.must_bound("The right operand of comparison is an unbound "
120 "boolean value.");
121 return boolean_value == other_value.boolean_value;
122 }
123
124 BOOLEAN::operator boolean() const
125 {
126 must_bound("Using the value of an unbound boolean variable.");
127 return boolean_value;
128 }
129
130 void BOOLEAN::clean_up()
131 {
132 bound_flag = FALSE;
133 }
134
135 void BOOLEAN::log() const
136 {
137 if (bound_flag) TTCN_Logger::log_event_str(boolean_value ? "true" : "false");
138 else TTCN_Logger::log_event_unbound();
139 }
140
141 void BOOLEAN::encode_text(Text_Buf& text_buf) const
142 {
143 must_bound("Text encoder: Encoding an unbound boolean value.");
144 text_buf.push_int(boolean_value ? 1 : 0);
145 }
146
147 void BOOLEAN::decode_text(Text_Buf& text_buf)
148 {
149 int int_value = text_buf.pull_int().get_val();
150 switch (int_value) {
151 case 0:
152 boolean_value = FALSE;
153 break;
154 case 1:
155 boolean_value = TRUE;
156 break;
157 default:
158 TTCN_error("Text decoder: An invalid boolean value (%d) was received.",
159 int_value);
160 }
161 bound_flag = TRUE;
162 }
163
164 void BOOLEAN::set_param(Module_Param& param) {
165 param.basic_check(Module_Param::BC_VALUE, "boolean value");
166 if (param.get_type()!=Module_Param::MP_Boolean) param.type_error("boolean value");
167 bound_flag = TRUE;
168 boolean_value = param.get_boolean();
169 }
170
171 void BOOLEAN::encode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf,
172 TTCN_EncDec::coding_t p_coding, ...) const
173 {
174 va_list pvar;
175 va_start(pvar, p_coding);
176 switch(p_coding) {
177 case TTCN_EncDec::CT_BER: {
178 TTCN_EncDec_ErrorContext ec("While BER-encoding type '%s': ", p_td.name);
179 unsigned BER_coding=va_arg(pvar, unsigned);
180 BER_encode_chk_coding(BER_coding);
181 ASN_BER_TLV_t *tlv=BER_encode_TLV(p_td, BER_coding);
182 tlv->put_in_buffer(p_buf);
183 ASN_BER_TLV_t::destruct(tlv);
184 break;}
185 case TTCN_EncDec::CT_RAW: {
186 TTCN_EncDec_ErrorContext ec("While RAW-encoding type '%s': ", p_td.name);
187 if(!p_td.raw)
188 TTCN_EncDec_ErrorContext::error_internal
189 ("No RAW descriptor available for type '%s'.", p_td.name);
190 RAW_enc_tr_pos rp;
191 rp.level=0;
192 rp.pos=NULL;
193 RAW_enc_tree root(TRUE,NULL,&rp,1,p_td.raw);
194 RAW_encode(p_td, root);
195 root.put_to_buf(p_buf);
196 break;}
197 case TTCN_EncDec::CT_TEXT: {
198 TTCN_EncDec_ErrorContext ec("While TEXT-encoding type '%s': ", p_td.name);
199 if(!p_td.text)
200 TTCN_EncDec_ErrorContext::error_internal
201 ("No TEXT descriptor available for type '%s'.", p_td.name);
202 TEXT_encode(p_td,p_buf);
203 break;}
204 case TTCN_EncDec::CT_XER: {
205 TTCN_EncDec_ErrorContext ec("While XER-encoding type '%s': ", p_td.name);
206 unsigned XER_coding=va_arg(pvar, unsigned);
207 XER_encode(*p_td.xer, p_buf, XER_coding, 0, 0);
208 break;}
209 case TTCN_EncDec::CT_JSON: {
210 TTCN_EncDec_ErrorContext ec("While JSON-encoding type '%s': ", p_td.name);
211 if(!p_td.json)
212 TTCN_EncDec_ErrorContext::error_internal
213 ("No JSON descriptor available for type '%s'.", p_td.name);
214 JSON_Tokenizer tok(va_arg(pvar, int) != 0);
215 JSON_encode(p_td, tok);
216 p_buf.put_s(tok.get_buffer_length(), (const unsigned char*)tok.get_buffer());
217 break;}
218 default:
219 TTCN_error("Unknown coding method requested to encode type '%s'",
220 p_td.name);
221 }
222 va_end(pvar);
223 }
224
225 void BOOLEAN::decode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf,
226 TTCN_EncDec::coding_t p_coding, ...)
227 {
228 va_list pvar;
229 va_start(pvar, p_coding);
230 switch(p_coding) {
231 case TTCN_EncDec::CT_BER: {
232 TTCN_EncDec_ErrorContext ec("While BER-decoding type '%s': ", p_td.name);
233 unsigned L_form=va_arg(pvar, unsigned);
234 ASN_BER_TLV_t tlv;
235 BER_decode_str2TLV(p_buf, tlv, L_form);
236 BER_decode_TLV(p_td, tlv, L_form);
237 if(tlv.isComplete) p_buf.increase_pos(tlv.get_len());
238 break;}
239 case TTCN_EncDec::CT_RAW: {
240 TTCN_EncDec_ErrorContext ec("While RAW-decoding type '%s': ", p_td.name);
241 if(!p_td.raw)
242 TTCN_EncDec_ErrorContext::error_internal
243 ("No RAW descriptor available for type '%s'.", p_td.name);
244 raw_order_t order;
245 switch(p_td.raw->top_bit_order){
246 case TOP_BIT_LEFT:
247 order=ORDER_LSB;
248 break;
249 case TOP_BIT_RIGHT:
250 default:
251 order=ORDER_MSB;
252 }
253 if(RAW_decode(p_td, p_buf, p_buf.get_len()*8, order)<0)
254 ec.error(TTCN_EncDec::ET_INCOMPL_MSG,
255 "Can not decode type '%s', because invalid or incomplete"
256 " message was received"
257 , p_td.name);
258 break;}
259 case TTCN_EncDec::CT_TEXT: {
260 Limit_Token_List limit;
261 TTCN_EncDec_ErrorContext ec("While TEXT-decoding type '%s': ", p_td.name);
262 if(!p_td.text)
263 TTCN_EncDec_ErrorContext::error_internal
264 ("No TEXT descriptor available for type '%s'.", p_td.name);
265 const unsigned char *b=p_buf.get_data();
266 if(b[p_buf.get_len()-1]!='\0'){
267 p_buf.set_pos(p_buf.get_len());
268 p_buf.put_zero(8,ORDER_LSB);
269 p_buf.rewind();
270 }
271 if(TEXT_decode(p_td,p_buf,limit)<0)
272 ec.error(TTCN_EncDec::ET_INCOMPL_MSG,
273 "Can not decode type '%s', because invalid or incomplete"
274 " message was received"
275 , p_td.name);
276 break;}
277 case TTCN_EncDec::CT_XER: {
278 TTCN_EncDec_ErrorContext ec("While XER-decoding type '%s': ", p_td.name);
279 unsigned XER_coding=va_arg(pvar, unsigned);
280 XmlReaderWrap reader(p_buf);
281 for (int success = reader.Read(); success==1; success=reader.Read()) {
282 int type = reader.NodeType();
283 if (type==XML_READER_TYPE_ELEMENT)
284 break;
285 }
286 XER_decode(*p_td.xer, reader, XER_coding, 0);
287 size_t bytes = reader.ByteConsumed();
288 p_buf.set_pos(bytes);
289 break;}
290 case TTCN_EncDec::CT_JSON: {
291 TTCN_EncDec_ErrorContext ec("While JSON-decoding type '%s': ", p_td.name);
292 if(!p_td.json)
293 TTCN_EncDec_ErrorContext::error_internal
294 ("No JSON descriptor available for type '%s'.", p_td.name);
295 JSON_Tokenizer tok((const char*)p_buf.get_data(), p_buf.get_len());
296 if(JSON_decode(p_td, tok, false)<0)
297 ec.error(TTCN_EncDec::ET_INCOMPL_MSG,
298 "Can not decode type '%s', because invalid or incomplete"
299 " message was received"
300 , p_td.name);
301 p_buf.set_pos(tok.get_buf_pos());
302 break;}
303 default:
304 TTCN_error("Unknown coding method requested to decode type '%s'",
305 p_td.name);
306 }
307 va_end(pvar);
308 }
309
310 ASN_BER_TLV_t*
311 BOOLEAN::BER_encode_TLV(const TTCN_Typedescriptor_t& p_td,
312 unsigned p_coding) const
313 {
314 BER_chk_descr(p_td);
315 ASN_BER_TLV_t *new_tlv=BER_encode_chk_bound(is_bound());
316 if(!new_tlv) {
317 new_tlv=ASN_BER_TLV_t::construct(1, NULL);
318 new_tlv->V.str.Vstr[0]=boolean_value==TRUE?0xFF:0x00;
319 }
320 new_tlv=ASN_BER_V2TLV(new_tlv, p_td, p_coding);
321 return new_tlv;
322 }
323
324 boolean BOOLEAN::BER_decode_TLV(const TTCN_Typedescriptor_t& p_td,
325 const ASN_BER_TLV_t& p_tlv,
326 unsigned L_form)
327 {
328 bound_flag = FALSE;
329 BER_chk_descr(p_td);
330 ASN_BER_TLV_t stripped_tlv;
331 BER_decode_strip_tags(*p_td.ber, p_tlv, L_form, stripped_tlv);
332 TTCN_EncDec_ErrorContext ec("While decoding BOOLEAN type: ");
333 stripped_tlv.chk_constructed_flag(FALSE);
334 if (!stripped_tlv.isComplete) return FALSE;
335 if(stripped_tlv.V.str.Vlen!=1)
336 ec.error(TTCN_EncDec::ET_INVAL_MSG,
337 "Length of V-part is %lu (instead of 1).",
338 (unsigned long) stripped_tlv.V.str.Vlen);
339 if(stripped_tlv.V.str.Vlen>=1) {
340 switch(stripped_tlv.V.str.Vstr[0]) {
341 case 0x00:
342 boolean_value=FALSE;
343 break;
344 default:
345 /* warning? */
346 case 0xFF:
347 boolean_value=TRUE;
348 break;
349 } // switch
350 bound_flag = TRUE;
351 return TRUE;
352 } else return FALSE;
353 }
354
355 int BOOLEAN::TEXT_decode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& buff,
356 Limit_Token_List&, boolean no_err, boolean /*first_call*/)
357 {
358
359 int decoded_length = 0;
360 int str_len = 0;
361 if (p_td.text->begin_decode) {
362 int tl;
363 if ((tl = p_td.text->begin_decode->match_begin(buff)) < 0) {
364 if (no_err) return -1;
365 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_TOKEN_ERR,
366 "The specified token '%s' not found for '%s': ",
367 (const char*) *(p_td.text->begin_decode), p_td.name);
368 return 0;
369 }
370 decoded_length += tl;
371 buff.increase_pos(tl);
372 }
373 if (buff.get_read_len() < 1 && no_err) return -TTCN_EncDec::ET_LEN_ERR;
374
375 boolean found = FALSE;
376
377 if ( p_td.text->val.bool_values
378 && p_td.text->val.bool_values->true_decode_token) {
379 int tl;
380 if ((tl = p_td.text->val.bool_values->true_decode_token->match_begin(buff)) > -1) {
381 str_len = tl;
382 found = TRUE;
383 boolean_value = TRUE;
384 }
385 }
386 else {
387 int tl;
388 if ((tl = boolean_true_match.match_begin(buff)) >= 0) {
389 str_len = tl;
390 found = TRUE;
391 boolean_value = TRUE;
392 }
393 }
394
395 if (!found) {
396 if ( p_td.text->val.bool_values
397 && p_td.text->val.bool_values->false_decode_token) {
398 int tl;
399 if ((tl = p_td.text->val.bool_values->false_decode_token->match_begin(buff)) > -1) {
400 str_len = tl;
401 found = TRUE;
402 boolean_value = FALSE;
403 }
404 }
405 else {
406 int tl;
407 if ((tl = boolean_false_match.match_begin(buff)) >= 0) {
408 str_len = tl;
409 found = TRUE;
410 boolean_value = FALSE;
411 }
412 }
413 }
414
415 if (found) {
416 decoded_length += str_len;
417 buff.increase_pos(str_len);
418 }
419 else {
420 if (no_err) return -1;
421 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_TOKEN_ERR,
422 "No boolean token found for '%s': ", p_td.name);
423 return decoded_length;
424 }
425
426 if (p_td.text->end_decode) {
427 int tl;
428 if ((tl = p_td.text->end_decode->match_begin(buff)) < 0) {
429 if (no_err) return -1;
430 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_TOKEN_ERR,
431 "The specified token '%s' not found for '%s': ",
432 (const char*) *(p_td.text->end_decode), p_td.name);
433 return 0;
434 }
435 decoded_length += tl;
436 buff.increase_pos(tl);
437 }
438 bound_flag = TRUE;
439 return decoded_length;
440 }
441
442
443 int BOOLEAN::TEXT_encode(const TTCN_Typedescriptor_t& p_td,
444 TTCN_Buffer& buff) const{
445 int encoded_length=0;
446 if(p_td.text->begin_encode){
447 buff.put_cs(*p_td.text->begin_encode);
448 encoded_length+=p_td.text->begin_encode->lengthof();
449 }
450 if(!is_bound()) {
451 TTCN_EncDec_ErrorContext::error
452 (TTCN_EncDec::ET_UNBOUND, "Encoding an unbound value.");
453 if(p_td.text->end_encode){
454 buff.put_cs(*p_td.text->end_encode);
455 encoded_length+=p_td.text->end_encode->lengthof();
456 }
457 return encoded_length;
458 }
459
460 if(p_td.text->val.bool_values==NULL){
461 if(boolean_value){
462 buff.put_s(4,(const unsigned char*)"true");
463 encoded_length+=4;
464 }
465 else {
466 buff.put_s(5,(const unsigned char*)"false");
467 encoded_length+=5;
468 }
469 } else {
470 if(boolean_value){
471 if(p_td.text->val.bool_values->true_encode_token){
472 buff.put_cs(*p_td.text->val.bool_values->true_encode_token);
473 encoded_length+=p_td.text->
474 val.bool_values->true_encode_token->lengthof();
475 } else {
476 buff.put_s(4,(const unsigned char*)"true");
477 encoded_length+=4;
478 }
479 }
480 else {
481 if(p_td.text->val.bool_values->false_encode_token){
482 buff.put_cs(*p_td.text->val.bool_values->false_encode_token);
483 encoded_length+=p_td.text->
484 val.bool_values->false_encode_token->lengthof();
485 } else {
486 buff.put_s(5,(const unsigned char*)"false");
487 encoded_length+=5;
488 }
489 }
490 }
491
492 if(p_td.text->end_encode){
493 buff.put_cs(*p_td.text->end_encode);
494 encoded_length+=p_td.text->end_encode->lengthof();
495 }
496 return encoded_length;
497 }
498
499 int BOOLEAN::RAW_encode(const TTCN_Typedescriptor_t& p_td, RAW_enc_tree& myleaf) const
500 {
501 unsigned char *bc;
502 int loc_length = p_td.raw->fieldlength ? p_td.raw->fieldlength : 1;
503 int length = (loc_length + 7) / 8;
504 unsigned char tmp;
505 if (!is_bound()) {
506 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND,
507 "Encoding an unbound value.");
508 tmp = '\0';
509 }
510 else tmp = boolean_value ? 0xFF : 0x00;
511 // myleaf.ext_bit=EXT_BIT_NO;
512 if (myleaf.must_free) Free(myleaf.body.leaf.data_ptr);
513 if (length > RAW_INT_ENC_LENGTH) {
514 myleaf.body.leaf.data_ptr = bc = (unsigned char*)Malloc(length*sizeof(*bc));
515 myleaf.must_free = TRUE;
516 myleaf.data_ptr_used = TRUE;
517 }
518 else bc = myleaf.body.leaf.data_array;
519
520 memset(bc, tmp, length * sizeof(*bc));
521 return myleaf.length = loc_length;
522 }
523
524 int BOOLEAN::RAW_decode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& buff,
525 int limit, raw_order_t top_bit_ord, boolean no_err, int /*sel_field*/,
526 boolean /*first_call*/)
527 {
528 bound_flag = FALSE;
529 int prepaddlength = buff.increase_pos_padd(p_td.raw->prepadding);
530 limit -= prepaddlength;
531 int decode_length = p_td.raw->fieldlength > 0 ? p_td.raw->fieldlength : 1;
532 if (decode_length > limit) {
533 if (no_err) return -TTCN_EncDec::ET_LEN_ERR;
534 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_LEN_ERR,
535 "There is not enough bits in the buffer to decode type %s (needed: %d, "
536 "found: %d).", p_td.name, decode_length, limit);
537 decode_length = limit;
538 }
539 int nof_unread_bits = buff.unread_len_bit();
540 if (decode_length > nof_unread_bits) {
541 if (no_err) return -TTCN_EncDec::ET_INCOMPL_MSG;
542 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_INCOMPL_MSG,
543 "There is not enough bits in the buffer to decode type %s (needed: %d, "
544 "found: %d).", p_td.name, decode_length, nof_unread_bits);
545 decode_length = nof_unread_bits;
546 }
547 if (decode_length < 0) return -1;
548 else if (decode_length == 0) boolean_value = FALSE;
549 else {
550 RAW_coding_par cp;
551 boolean orders = FALSE;
552 if (p_td.raw->bitorderinoctet == ORDER_MSB) orders = TRUE;
553 if (p_td.raw->bitorderinfield == ORDER_MSB) orders = !orders;
554 cp.bitorder = orders ? ORDER_MSB : ORDER_LSB;
555 orders = FALSE;
556 if (p_td.raw->byteorder == ORDER_MSB) orders = TRUE;
557 if (p_td.raw->bitorderinfield == ORDER_MSB) orders = !orders;
558 cp.byteorder = orders ? ORDER_MSB : ORDER_LSB;
559 cp.fieldorder = p_td.raw->fieldorder;
560 cp.hexorder = ORDER_LSB;
561 int length = (decode_length + 7) / 8;
562 unsigned char *data = (unsigned char*)Malloc(length*sizeof(unsigned char));
563 buff.get_b((size_t)decode_length, data, cp, top_bit_ord);
564 if(decode_length % 8){
565 data[length - 1] &= BitMaskTable[decode_length % 8];
566 }
567 unsigned char ch = '\0';
568 for (int a = 0; a < length; a++) ch |= data[a];
569 Free(data);
570 boolean_value = ch != '\0';
571 }
572 bound_flag = TRUE;
573 decode_length += buff.increase_pos_padd(p_td.raw->padding);
574 return decode_length + prepaddlength;
575 }
576
577 int BOOLEAN::XER_encode(const XERdescriptor_t& p_td,
578 TTCN_Buffer& p_buf, unsigned int flavor, int indent, embed_values_enc_struct_t*) const
579 {
580 if(!is_bound()) {
581 TTCN_EncDec_ErrorContext::error
582 (TTCN_EncDec::ET_UNBOUND, "Encoding an unbound boolean value.");
583 }
584 int encoded_length=(int)p_buf.get_len();
585
586 int exer = is_exer(flavor);
587
588 flavor |= (SIMPLE_TYPE | BXER_EMPTY_ELEM);
589 if (begin_xml(p_td, p_buf, flavor, indent, false) == -1) --encoded_length;
590
591 if (exer) {
592 if (p_td.xer_bits & XER_TEXT) {
593 p_buf.put_c(boolean_value ? '1' : '0');
594 }
595 else {
596 if (boolean_value) p_buf.put_s(4, (cbyte*)"true");
597 else p_buf.put_s(5, (cbyte*)"false");
598 }
599 }
600 else {
601 if (boolean_value) p_buf.put_s(7, (cbyte*)"<true/>");
602 else p_buf.put_s(8, (cbyte*)"<false/>");
603 }
604
605 end_xml(p_td, p_buf, flavor, indent, false);
606
607 return (int)p_buf.get_len() - encoded_length;
608 }
609
610 int BOOLEAN::XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& reader,
611 unsigned int flavor, embed_values_dec_struct_t*)
612 {
613 const boolean exer = is_exer(flavor);
614 int XMLValueList = !exer && is_record_of(flavor);
615 const boolean notag = (exer && (p_td.xer_bits & (UNTAGGED))) ||
616 is_exerlist(flavor) || XMLValueList;
617 int depth = -1, success, type;
618 const char *value = 0;
619
620 if (exer && (p_td.xer_bits & XER_ATTRIBUTE)) {
621 verify_name(reader, p_td, exer);
622 value = (const char *)reader.Value();
623 }
624 else {
625 for (success = reader.Ok(); success == 1; success = reader.Read()) {
626 type = reader.NodeType();
627 if (!notag && depth == -1) {
628 if (XML_READER_TYPE_ELEMENT == type) {
629 verify_name(reader, p_td, exer);
630 depth = reader.Depth();
631
632 if (exer && (p_td.dfeValue != 0) && reader.IsEmptyElement()) {
633 *this = *static_cast<const BOOLEAN*>(p_td.dfeValue);
634 (void)reader.Read();
635 goto fini;
636 }
637 continue;
638 } // if type
639 }
640 else { // found the enclosing tag already
641 if (!exer && XML_READER_TYPE_ELEMENT == type) {
642 // this must be EmptyElement Boolean
643 if (!reader.IsEmptyElement()) TTCN_EncDec_ErrorContext::error(
644 TTCN_EncDec::ET_INVAL_MSG, "Boolean must be empty element");
645 value = (const char*)reader.LocalName();
646 }
647 else if (XML_READER_TYPE_TEXT == type) {
648 // TextBoolean
649 value = (const char*)reader.Value();
650 }
651
652 // Must not modify the buffer when attempting to find the selected alternative for USE-UNION
653 if (!exer || !(flavor & EXIT_ON_ERROR)) reader.Read();
654 break;
655 } // if depth
656 } // next read
657 } // if not attribute
658
659 if (value != 0 && *value != 0) {
660 // extract the data
661 if (value[1]=='\0' && (*value & 0x3E) == '0')
662 {
663 bound_flag = true;
664 boolean_value = *value == '1';
665 }
666 else if (!strcmp(value, "true")) {
667 boolean_value = true;
668 bound_flag = true;
669 }
670 else if (!strcmp(value, "false")) {
671 boolean_value = false;
672 bound_flag = true;
673 }
674
675 }
676
677 if (exer && (p_td.xer_bits & XER_ATTRIBUTE)) { // I am an attribute
678 // Let the caller do reader.AdvanceAttribute();
679 }
680 else if (!notag) {
681 for (success = reader.Ok(); success == 1; success = reader.Read()) {
682 type = reader.NodeType();
683 if (XML_READER_TYPE_END_ELEMENT == type) {
684 verify_end(reader, p_td, depth, exer);
685 reader.Read(); // one last time
686 break;
687 }
688 } // next
689 }
690 fini:
691 return 1;
692 }
693
694 int BOOLEAN::JSON_encode(const TTCN_Typedescriptor_t&, JSON_Tokenizer& p_tok) const
695 {
696 if (!is_bound()) {
697 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND,
698 "Encoding an unbound boolean value.");
699 return -1;
700 }
701 return p_tok.put_next_token((boolean_value) ? JSON_TOKEN_LITERAL_TRUE : JSON_TOKEN_LITERAL_FALSE, NULL);
702 }
703
704 int BOOLEAN::JSON_decode(const TTCN_Typedescriptor_t& p_td, JSON_Tokenizer& p_tok, boolean p_silent)
705 {
706 json_token_t token = JSON_TOKEN_NONE;
707 int dec_len = 0;
708 if (p_td.json->default_value && 0 == p_tok.get_buffer_length()) {
709 // No JSON data in the buffer -> use default value
710 if (strcmp(p_td.json->default_value, "true") == 0) {
711 token = JSON_TOKEN_LITERAL_TRUE;
712 }
713 else {
714 token = JSON_TOKEN_LITERAL_FALSE;
715 }
716 } else {
717 dec_len = p_tok.get_next_token(&token, NULL, NULL);
718 }
719 if (JSON_TOKEN_ERROR == token) {
720 JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_BAD_TOKEN_ERROR, "");
721 return JSON_ERROR_FATAL;
722 }
723 else if (JSON_TOKEN_LITERAL_TRUE == token) {
724 bound_flag = true;
725 boolean_value = true;
726 }
727 else if (JSON_TOKEN_LITERAL_FALSE == token) {
728 bound_flag = true;
729 boolean_value = false;
730 }
731 else {
732 bound_flag = false;
733 return JSON_ERROR_INVALID_TOKEN;
734 }
735 return dec_len;
736 }
737
738
739 boolean operator&&(boolean bool_value, const BOOLEAN& other_value)
740 {
741 if (!bool_value) return FALSE;
742 other_value.must_bound("The right operand of and operator is an unbound "
743 "boolean value.");
744 return other_value.boolean_value;
745 }
746
747 boolean operator^(boolean bool_value, const BOOLEAN& other_value)
748 {
749 other_value.must_bound("The right operand of xor operator is an unbound "
750 "boolean value.");
751 return bool_value != other_value.boolean_value;
752 }
753
754 boolean operator||(boolean bool_value, const BOOLEAN& other_value)
755 {
756 if (bool_value) return TRUE;
757 other_value.must_bound("The right operand of or operator is an unbound "
758 "boolean value.");
759 return other_value.boolean_value;
760 }
761
762 boolean operator==(boolean bool_value, const BOOLEAN& other_value)
763 {
764 other_value.must_bound("The right operand of comparison is an unbound "
765 "boolean value.");
766 return bool_value == other_value.boolean_value;
767 }
768
769 void BOOLEAN_template::clean_up()
770 {
771 if (template_selection == VALUE_LIST ||
772 template_selection == COMPLEMENTED_LIST)
773 delete [] value_list.list_value;
774 template_selection = UNINITIALIZED_TEMPLATE;
775 }
776
777 void BOOLEAN_template::copy_template(const BOOLEAN_template& other_value)
778 {
779 switch (other_value.template_selection) {
780 case SPECIFIC_VALUE:
781 single_value = other_value.single_value;
782 break;
783 case OMIT_VALUE:
784 case ANY_VALUE:
785 case ANY_OR_OMIT:
786 break;
787 case VALUE_LIST:
788 case COMPLEMENTED_LIST:
789 value_list.n_values = other_value.value_list.n_values;
790 value_list.list_value = new BOOLEAN_template[value_list.n_values];
791 for (unsigned int i = 0; i < value_list.n_values; i++)
792 value_list.list_value[i].copy_template(
793 other_value.value_list.list_value[i]);
794 break;
795 default:
796 TTCN_error("Copying an uninitialized/unsupported boolean template.");
797 }
798 set_selection(other_value);
799 }
800
801 BOOLEAN_template::BOOLEAN_template()
802 {
803
804 }
805
806 BOOLEAN_template::BOOLEAN_template(template_sel other_value)
807 : Base_Template(other_value)
808 {
809 check_single_selection(other_value);
810 }
811
812 BOOLEAN_template::BOOLEAN_template(boolean other_value)
813 : Base_Template(SPECIFIC_VALUE)
814 {
815 single_value = other_value;
816 }
817
818 BOOLEAN_template::BOOLEAN_template(const BOOLEAN& other_value)
819 : Base_Template(SPECIFIC_VALUE)
820 {
821 other_value.must_bound("Creating a template from an unbound integer value.");
822 single_value = other_value.boolean_value;
823 }
824
825 BOOLEAN_template::BOOLEAN_template(const OPTIONAL<BOOLEAN>& other_value)
826 {
827 switch (other_value.get_selection()) {
828 case OPTIONAL_PRESENT:
829 set_selection(SPECIFIC_VALUE);
830 single_value = (boolean)(const BOOLEAN&)other_value;
831 break;
832 case OPTIONAL_OMIT:
833 set_selection(OMIT_VALUE);
834 break;
835 default:
836 TTCN_error("Creating a boolean template from an unbound optional field.");
837 }
838 }
839
840 BOOLEAN_template::BOOLEAN_template(const BOOLEAN_template& other_value)
841 : Base_Template()
842 {
843 copy_template(other_value);
844 }
845
846 BOOLEAN_template::~BOOLEAN_template()
847 {
848 clean_up();
849 }
850
851 BOOLEAN_template& BOOLEAN_template::operator=(template_sel other_value)
852 {
853 check_single_selection(other_value);
854 clean_up();
855 set_selection(other_value);
856 return *this;
857 }
858
859 BOOLEAN_template& BOOLEAN_template::operator=(boolean other_value)
860 {
861 clean_up();
862 set_selection(SPECIFIC_VALUE);
863 single_value = other_value;
864 return *this;
865 }
866
867 BOOLEAN_template& BOOLEAN_template::operator=(const BOOLEAN& other_value)
868 {
869 other_value.must_bound("Assignment of an unbound boolean value to a "
870 "template.");
871 clean_up();
872 set_selection(SPECIFIC_VALUE);
873 single_value = other_value.boolean_value;
874 return *this;
875 }
876
877 BOOLEAN_template& BOOLEAN_template::operator=
878 (const OPTIONAL<BOOLEAN>& other_value)
879 {
880 clean_up();
881 switch (other_value.get_selection()) {
882 case OPTIONAL_PRESENT:
883 set_selection(SPECIFIC_VALUE);
884 single_value = (boolean)(const BOOLEAN&)other_value;
885 break;
886 case OPTIONAL_OMIT:
887 set_selection(OMIT_VALUE);
888 break;
889 default:
890 TTCN_error("Assignment of an unbound optional field to a boolean "
891 "template.");
892 }
893 return *this;
894 }
895
896 BOOLEAN_template& BOOLEAN_template::operator=
897 (const BOOLEAN_template& other_value)
898 {
899 if (&other_value != this) {
900 clean_up();
901 copy_template(other_value);
902 }
903 return *this;
904 }
905
906 boolean BOOLEAN_template::match(boolean other_value) const
907 {
908 switch (template_selection) {
909 case SPECIFIC_VALUE:
910 return single_value == other_value;
911 case OMIT_VALUE:
912 return FALSE;
913 case ANY_VALUE:
914 case ANY_OR_OMIT:
915 return TRUE;
916 case VALUE_LIST:
917 case COMPLEMENTED_LIST:
918 for (unsigned int i = 0; i < value_list.n_values; i++)
919 if (value_list.list_value[i].match(other_value))
920 return template_selection == VALUE_LIST;
921 return template_selection == COMPLEMENTED_LIST;
922 default:
923 TTCN_error("Matching with an uninitialized/unsupported boolean template.");
924 }
925 return FALSE;
926 }
927
928 boolean BOOLEAN_template::match(const BOOLEAN& other_value) const
929 {
930 if (!other_value.is_bound()) return FALSE;
931 return match(other_value.boolean_value);
932 }
933
934 boolean BOOLEAN_template::valueof() const
935 {
936 if (template_selection != SPECIFIC_VALUE || is_ifpresent)
937 TTCN_error("Performing valueof or "
938 "send operation on a non-specific boolean template.");
939 return single_value;
940 }
941
942 void BOOLEAN_template::set_type(template_sel template_type,
943 unsigned int list_length)
944 {
945 if (template_type != VALUE_LIST && template_type != COMPLEMENTED_LIST)
946 TTCN_error("Setting an invalid list type for a boolean template.");
947 clean_up();
948 set_selection(template_type);
949 value_list.n_values = list_length;
950 value_list.list_value = new BOOLEAN_template[list_length];
951 }
952
953 BOOLEAN_template& BOOLEAN_template::list_item(unsigned int list_index)
954 {
955 if (template_selection != VALUE_LIST &&
956 template_selection != COMPLEMENTED_LIST)
957 TTCN_error("Accessing a list element of a non-list boolean template.");
958 if (list_index >= value_list.n_values)
959 TTCN_error("Index overflow in a boolean value list template.");
960 return value_list.list_value[list_index];
961 }
962
963 void BOOLEAN_template::log() const
964 {
965 switch (template_selection) {
966 case SPECIFIC_VALUE:
967 TTCN_Logger::log_event_str(single_value ? "true" : "false");
968 break;
969 case COMPLEMENTED_LIST:
970 TTCN_Logger::log_event_str("complement ");
971 // no break
972 case VALUE_LIST:
973 TTCN_Logger::log_char('(');
974 for (unsigned int i = 0; i < value_list.n_values; i++) {
975 if (i > 0) TTCN_Logger::log_event_str(", ");
976 value_list.list_value[i].log();
977 }
978 TTCN_Logger::log_char(')');
979 break;
980 default:
981 log_generic();
982 break;
983 }
984 log_ifpresent();
985 }
986
987 void BOOLEAN_template::log_match(const BOOLEAN& match_value) const
988 {
989 if (TTCN_Logger::VERBOSITY_COMPACT == TTCN_Logger::get_matching_verbosity()
990 && TTCN_Logger::get_logmatch_buffer_len() != 0) {
991 TTCN_Logger::print_logmatch_buffer();
992 TTCN_Logger::log_event_str(" := ");
993 }
994 match_value.log();
995 TTCN_Logger::log_event_str(" with ");
996 log();
997 if (match(match_value)) TTCN_Logger::log_event_str(" matched");
998 else TTCN_Logger::log_event_str(" unmatched");
999 }
1000
1001 void BOOLEAN_template::set_param(Module_Param& param) {
1002 param.basic_check(Module_Param::BC_TEMPLATE, "boolean template");
1003 switch (param.get_type()) {
1004 case Module_Param::MP_Omit:
1005 *this = OMIT_VALUE;
1006 break;
1007 case Module_Param::MP_Any:
1008 *this = ANY_VALUE;
1009 break;
1010 case Module_Param::MP_AnyOrNone:
1011 *this = ANY_OR_OMIT;
1012 break;
1013 case Module_Param::MP_List_Template:
1014 case Module_Param::MP_ComplementList_Template:
1015 set_type(param.get_type()==Module_Param::MP_List_Template ? VALUE_LIST : COMPLEMENTED_LIST, param.get_size());
1016 for (size_t i=0; i<param.get_size(); i++) {
1017 list_item(i).set_param(*param.get_elem(i));
1018 }
1019 break;
1020 case Module_Param::MP_Boolean:
1021 *this = param.get_boolean();
1022 break;
1023 default:
1024 param.type_error("boolean template");
1025 }
1026 is_ifpresent = param.get_ifpresent();
1027 }
1028
1029 void BOOLEAN_template::encode_text(Text_Buf& text_buf) const
1030 {
1031 encode_text_base(text_buf);
1032 switch (template_selection) {
1033 case OMIT_VALUE:
1034 case ANY_VALUE:
1035 case ANY_OR_OMIT:
1036 break;
1037 case SPECIFIC_VALUE:
1038 text_buf.push_int(single_value ? 1 : 0);
1039 break;
1040 case VALUE_LIST:
1041 case COMPLEMENTED_LIST:
1042 text_buf.push_int(value_list.n_values);
1043 for (unsigned int i = 0; i < value_list.n_values; i++)
1044 value_list.list_value[i].encode_text(text_buf);
1045 break;
1046 default:
1047 TTCN_error("Text encoder: Encoding an uninitialized/unsupported boolean "
1048 "template.");
1049 }
1050 }
1051
1052 void BOOLEAN_template::decode_text(Text_Buf& text_buf)
1053 {
1054 clean_up();
1055 decode_text_base(text_buf);
1056 switch (template_selection) {
1057 case OMIT_VALUE:
1058 case ANY_VALUE:
1059 case ANY_OR_OMIT:
1060 break;
1061 case SPECIFIC_VALUE: {
1062 int int_value = text_buf.pull_int().get_val();
1063 switch (int_value) {
1064 case 0:
1065 single_value = FALSE;
1066 break;
1067 case 1:
1068 single_value = TRUE;
1069 break;
1070 default:
1071 TTCN_error("Text decoder: An invalid boolean value (%d) was received for "
1072 "a template.", int_value);
1073 }
1074 break; }
1075 case VALUE_LIST:
1076 case COMPLEMENTED_LIST:
1077 value_list.n_values = text_buf.pull_int().get_val();
1078 value_list.list_value = new BOOLEAN_template[value_list.n_values];
1079 for (unsigned int i = 0; i < value_list.n_values; i++)
1080 value_list.list_value[i].decode_text(text_buf);
1081 break;
1082 default:
1083 TTCN_error("Text decoder: An unknown/unsupported selection was "
1084 "received for a boolean template.");
1085 }
1086 }
1087
1088 boolean BOOLEAN_template::is_present() const
1089 {
1090 if (template_selection==UNINITIALIZED_TEMPLATE) return FALSE;
1091 return !match_omit();
1092 }
1093
1094 boolean BOOLEAN_template::match_omit() const
1095 {
1096 if (is_ifpresent) return TRUE;
1097 switch (template_selection) {
1098 case OMIT_VALUE:
1099 case ANY_OR_OMIT:
1100 return TRUE;
1101 case VALUE_LIST:
1102 case COMPLEMENTED_LIST:
1103 for (unsigned int i=0; i<value_list.n_values; i++)
1104 if (value_list.list_value[i].match_omit())
1105 return template_selection==VALUE_LIST;
1106 return template_selection==COMPLEMENTED_LIST;
1107 default:
1108 return FALSE;
1109 }
1110 return FALSE;
1111 }
1112
1113 #ifndef TITAN_RUNTIME_2
1114 void BOOLEAN_template::check_restriction(template_res t_res, const char* t_name) const
1115 {
1116 if (template_selection==UNINITIALIZED_TEMPLATE) return;
1117 switch ((t_name&&(t_res==TR_VALUE))?TR_OMIT:t_res) {
1118 case TR_VALUE:
1119 if (!is_ifpresent && template_selection==SPECIFIC_VALUE) return;
1120 break;
1121 case TR_OMIT:
1122 if (!is_ifpresent && (template_selection==OMIT_VALUE ||
1123 template_selection==SPECIFIC_VALUE)) return;
1124 break;
1125 case TR_PRESENT:
1126 if (!match_omit()) return;
1127 break;
1128 default:
1129 return;
1130 }
1131 TTCN_error("Restriction `%s' on template of type %s violated.",
1132 get_res_name(t_res), t_name ? t_name : "boolean");
1133 }
1134 #endif
This page took 0.054473 seconds and 5 git commands to generate.