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