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