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 ///////////////////////////////////////////////////////////////////////////////
11 #include "../common/memory.h"
12 #include "Parameters.h"
13 #include "Param_Types.hh"
20 #include "Charstring.hh"
21 #include "XmlReader.hh"
23 static const Token_Match
boolean_true_match("^(true).*$",TRUE
);
24 static const Token_Match
boolean_false_match("^(false).*$",TRUE
);
31 BOOLEAN::BOOLEAN(boolean other_value
)
34 boolean_value
= other_value
;
37 BOOLEAN::BOOLEAN(const BOOLEAN
& other_value
)
38 : Base_Type(other_value
)
40 other_value
.must_bound("Copying an unbound boolean value.");
42 boolean_value
= other_value
.boolean_value
;
45 BOOLEAN
& BOOLEAN::operator=(boolean other_value
)
48 boolean_value
= other_value
;
52 BOOLEAN
& BOOLEAN::operator=(const BOOLEAN
& other_value
)
54 other_value
.must_bound("Assignment of an unbound boolean value.");
56 boolean_value
= other_value
.boolean_value
;
60 boolean
BOOLEAN::operator!() const
62 must_bound("The operand of not operator is an unbound boolean value.");
63 return !boolean_value
;
66 boolean
BOOLEAN::operator&&(boolean other_value
) const
68 must_bound("The left operand of and operator is an unbound boolean value.");
69 return boolean_value
&& other_value
;
72 boolean
BOOLEAN::operator&&(const BOOLEAN
& other_value
) const
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 "
78 return other_value
.boolean_value
;
81 boolean
BOOLEAN::operator^(boolean other_value
) const
83 must_bound("The left operand of xor operator is an unbound boolean value.");
84 return boolean_value
!= other_value
;
87 boolean
BOOLEAN::operator^(const BOOLEAN
& other_value
) const
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 "
92 return boolean_value
!= other_value
.boolean_value
;
95 boolean
BOOLEAN::operator||(boolean other_value
) const
97 must_bound("The left operand of or operator is an unbound boolean value.");
98 return boolean_value
|| other_value
;
101 boolean
BOOLEAN::operator||(const BOOLEAN
& other_value
) const
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 "
107 return other_value
.boolean_value
;
110 boolean
BOOLEAN::operator==(boolean other_value
) const
112 must_bound("The left operand of comparison is an unbound boolean value.");
113 return boolean_value
== other_value
;
116 boolean
BOOLEAN::operator==(const BOOLEAN
& other_value
) const
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 "
121 return boolean_value
== other_value
.boolean_value
;
124 BOOLEAN::operator boolean() const
126 must_bound("Using the value of an unbound boolean variable.");
127 return boolean_value
;
130 void BOOLEAN::clean_up()
135 void BOOLEAN::log() const
137 if (bound_flag
) TTCN_Logger::log_event_str(boolean_value
? "true" : "false");
138 else TTCN_Logger::log_event_unbound();
141 void BOOLEAN::encode_text(Text_Buf
& text_buf
) const
143 must_bound("Text encoder: Encoding an unbound boolean value.");
144 text_buf
.push_int(boolean_value
? 1 : 0);
147 void BOOLEAN::decode_text(Text_Buf
& text_buf
)
149 int int_value
= text_buf
.pull_int().get_val();
152 boolean_value
= FALSE
;
155 boolean_value
= TRUE
;
158 TTCN_error("Text decoder: An invalid boolean value (%d) was received.",
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");
168 boolean_value
= param
.get_boolean();
171 void BOOLEAN::encode(const TTCN_Typedescriptor_t
& p_td
, TTCN_Buffer
& p_buf
,
172 TTCN_EncDec::coding_t p_coding
, ...) const
175 va_start(pvar
, 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
);
185 case TTCN_EncDec::CT_RAW
: {
186 TTCN_EncDec_ErrorContext
ec("While RAW-encoding type '%s': ", p_td
.name
);
188 TTCN_EncDec_ErrorContext::error_internal
189 ("No RAW descriptor available for type '%s'.", p_td
.name
);
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
);
197 case TTCN_EncDec::CT_TEXT
: {
198 TTCN_EncDec_ErrorContext
ec("While TEXT-encoding type '%s': ", p_td
.name
);
200 TTCN_EncDec_ErrorContext::error_internal
201 ("No TEXT descriptor available for type '%s'.", p_td
.name
);
202 TEXT_encode(p_td
,p_buf
);
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);
209 case TTCN_EncDec::CT_JSON
: {
210 TTCN_EncDec_ErrorContext
ec("While JSON-encoding type '%s': ", p_td
.name
);
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());
219 TTCN_error("Unknown coding method requested to encode type '%s'",
225 void BOOLEAN::decode(const TTCN_Typedescriptor_t
& p_td
, TTCN_Buffer
& p_buf
,
226 TTCN_EncDec::coding_t p_coding
, ...)
229 va_start(pvar
, 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);
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());
239 case TTCN_EncDec::CT_RAW
: {
240 TTCN_EncDec_ErrorContext
ec("While RAW-decoding type '%s': ", p_td
.name
);
242 TTCN_EncDec_ErrorContext::error_internal
243 ("No RAW descriptor available for type '%s'.", p_td
.name
);
245 switch(p_td
.raw
->top_bit_order
){
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"
259 case TTCN_EncDec::CT_TEXT
: {
260 Limit_Token_List limit
;
261 TTCN_EncDec_ErrorContext
ec("While TEXT-decoding type '%s': ", p_td
.name
);
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
);
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"
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
)
286 XER_decode(*p_td
.xer
, reader
, XER_coding
, 0);
287 size_t bytes
= reader
.ByteConsumed();
288 p_buf
.set_pos(bytes
);
290 case TTCN_EncDec::CT_JSON
: {
291 TTCN_EncDec_ErrorContext
ec("While JSON-decoding type '%s': ", p_td
.name
);
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"
301 p_buf
.set_pos(tok
.get_buf_pos());
304 TTCN_error("Unknown coding method requested to decode type '%s'",
311 BOOLEAN::BER_encode_TLV(const TTCN_Typedescriptor_t
& p_td
,
312 unsigned p_coding
) const
315 ASN_BER_TLV_t
*new_tlv
=BER_encode_chk_bound(is_bound());
317 new_tlv
=ASN_BER_TLV_t::construct(1, NULL
);
318 new_tlv
->V
.str
.Vstr
[0]=boolean_value
==TRUE
?0xFF:0x00;
320 new_tlv
=ASN_BER_V2TLV(new_tlv
, p_td
, p_coding
);
324 boolean
BOOLEAN::BER_decode_TLV(const TTCN_Typedescriptor_t
& p_td
,
325 const ASN_BER_TLV_t
& p_tlv
,
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]) {
355 int BOOLEAN::TEXT_decode(const TTCN_Typedescriptor_t
& p_td
, TTCN_Buffer
& buff
,
356 Limit_Token_List
&, boolean no_err
, boolean
/*first_call*/)
359 int decoded_length
= 0;
361 if (p_td
.text
->begin_decode
) {
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
);
370 decoded_length
+= tl
;
371 buff
.increase_pos(tl
);
373 if (buff
.get_read_len() < 1 && no_err
) return -TTCN_EncDec::ET_LEN_ERR
;
375 boolean found
= FALSE
;
377 if ( p_td
.text
->val
.bool_values
378 && p_td
.text
->val
.bool_values
->true_decode_token
) {
380 if ((tl
= p_td
.text
->val
.bool_values
->true_decode_token
->match_begin(buff
)) > -1) {
383 boolean_value
= TRUE
;
388 if ((tl
= boolean_true_match
.match_begin(buff
)) >= 0) {
391 boolean_value
= TRUE
;
396 if ( p_td
.text
->val
.bool_values
397 && p_td
.text
->val
.bool_values
->false_decode_token
) {
399 if ((tl
= p_td
.text
->val
.bool_values
->false_decode_token
->match_begin(buff
)) > -1) {
402 boolean_value
= FALSE
;
407 if ((tl
= boolean_false_match
.match_begin(buff
)) >= 0) {
410 boolean_value
= FALSE
;
416 decoded_length
+= str_len
;
417 buff
.increase_pos(str_len
);
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
;
426 if (p_td
.text
->end_decode
) {
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
);
435 decoded_length
+= tl
;
436 buff
.increase_pos(tl
);
439 return decoded_length
;
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();
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();
457 return encoded_length
;
460 if(p_td
.text
->val
.bool_values
==NULL
){
462 buff
.put_s(4,(const unsigned char*)"true");
466 buff
.put_s(5,(const unsigned char*)"false");
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();
476 buff
.put_s(4,(const unsigned char*)"true");
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();
486 buff
.put_s(5,(const unsigned char*)"false");
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();
496 return encoded_length
;
499 int BOOLEAN::RAW_encode(const TTCN_Typedescriptor_t
& p_td
, RAW_enc_tree
& myleaf
) const
502 int loc_length
= p_td
.raw
->fieldlength
? p_td
.raw
->fieldlength
: 1;
503 int length
= (loc_length
+ 7) / 8;
506 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND
,
507 "Encoding an unbound value.");
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
;
518 else bc
= myleaf
.body
.leaf
.data_array
;
520 memset(bc
, tmp
, length
* sizeof(*bc
));
521 return myleaf
.length
= loc_length
;
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*/)
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
;
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
;
547 if (decode_length
< 0) return -1;
548 else if (decode_length
== 0) boolean_value
= FALSE
;
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
;
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];
567 unsigned char ch
= '\0';
568 for (int a
= 0; a
< length
; a
++) ch
|= data
[a
];
570 boolean_value
= ch
!= '\0';
573 decode_length
+= buff
.increase_pos_padd(p_td
.raw
->padding
);
574 return decode_length
+ prepaddlength
;
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
581 TTCN_EncDec_ErrorContext::error
582 (TTCN_EncDec::ET_UNBOUND
, "Encoding an unbound boolean value.");
584 int encoded_length
=(int)p_buf
.get_len();
586 int exer
= is_exer(flavor
);
588 flavor
|= (SIMPLE_TYPE
| BXER_EMPTY_ELEM
);
589 if (begin_xml(p_td
, p_buf
, flavor
, indent
, false) == -1) --encoded_length
;
592 if (p_td
.xer_bits
& XER_TEXT
) {
593 p_buf
.put_c(boolean_value
? '1' : '0');
596 if (boolean_value
) p_buf
.put_s(4, (cbyte
*)"true");
597 else p_buf
.put_s(5, (cbyte
*)"false");
601 if (boolean_value
) p_buf
.put_s(7, (cbyte
*)"<true/>");
602 else p_buf
.put_s(8, (cbyte
*)"<false/>");
605 end_xml(p_td
, p_buf
, flavor
, indent
, false);
607 return (int)p_buf
.get_len() - encoded_length
;
610 int BOOLEAN::XER_decode(const XERdescriptor_t
& p_td
, XmlReaderWrap
& reader
,
611 unsigned int flavor
, embed_values_dec_struct_t
*)
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;
620 if (exer
&& (p_td
.xer_bits
& XER_ATTRIBUTE
)) {
621 verify_name(reader
, p_td
, exer
);
622 value
= (const char *)reader
.Value();
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();
632 if (exer
&& (p_td
.dfeValue
!= 0) && reader
.IsEmptyElement()) {
633 *this = *static_cast<const BOOLEAN
*>(p_td
.dfeValue
);
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();
647 else if (XML_READER_TYPE_TEXT
== type
) {
649 value
= (const char*)reader
.Value();
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();
657 } // if not attribute
659 if (value
!= 0 && *value
!= 0) {
661 if (value
[1]=='\0' && (*value
& 0x3E) == '0')
664 boolean_value
= *value
== '1';
666 else if (!strcmp(value
, "true")) {
667 boolean_value
= true;
670 else if (!strcmp(value
, "false")) {
671 boolean_value
= false;
677 if (exer
&& (p_td
.xer_bits
& XER_ATTRIBUTE
)) { // I am an attribute
678 // Let the caller do reader.AdvanceAttribute();
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
694 int BOOLEAN::JSON_encode(const TTCN_Typedescriptor_t
&, JSON_Tokenizer
& p_tok
) const
697 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND
,
698 "Encoding an unbound boolean value.");
701 return p_tok
.put_next_token((boolean_value
) ? JSON_TOKEN_LITERAL_TRUE
: JSON_TOKEN_LITERAL_FALSE
, NULL
);
704 int BOOLEAN::JSON_decode(const TTCN_Typedescriptor_t
& p_td
, JSON_Tokenizer
& p_tok
, boolean p_silent
)
706 json_token_t token
= JSON_TOKEN_NONE
;
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
;
714 token
= JSON_TOKEN_LITERAL_FALSE
;
717 dec_len
= p_tok
.get_next_token(&token
, NULL
, NULL
);
719 if (JSON_TOKEN_ERROR
== token
) {
720 JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG
, JSON_DEC_BAD_TOKEN_ERROR
, "");
721 return JSON_ERROR_FATAL
;
723 else if (JSON_TOKEN_LITERAL_TRUE
== token
) {
725 boolean_value
= true;
727 else if (JSON_TOKEN_LITERAL_FALSE
== token
) {
729 boolean_value
= false;
733 return JSON_ERROR_INVALID_TOKEN
;
739 boolean
operator&&(boolean bool_value
, const BOOLEAN
& other_value
)
741 if (!bool_value
) return FALSE
;
742 other_value
.must_bound("The right operand of and operator is an unbound "
744 return other_value
.boolean_value
;
747 boolean
operator^(boolean bool_value
, const BOOLEAN
& other_value
)
749 other_value
.must_bound("The right operand of xor operator is an unbound "
751 return bool_value
!= other_value
.boolean_value
;
754 boolean
operator||(boolean bool_value
, const BOOLEAN
& other_value
)
756 if (bool_value
) return TRUE
;
757 other_value
.must_bound("The right operand of or operator is an unbound "
759 return other_value
.boolean_value
;
762 boolean
operator==(boolean bool_value
, const BOOLEAN
& other_value
)
764 other_value
.must_bound("The right operand of comparison is an unbound "
766 return bool_value
== other_value
.boolean_value
;
769 void BOOLEAN_template::clean_up()
771 if (template_selection
== VALUE_LIST
||
772 template_selection
== COMPLEMENTED_LIST
)
773 delete [] value_list
.list_value
;
774 template_selection
= UNINITIALIZED_TEMPLATE
;
777 void BOOLEAN_template::copy_template(const BOOLEAN_template
& other_value
)
779 switch (other_value
.template_selection
) {
781 single_value
= other_value
.single_value
;
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
]);
796 TTCN_error("Copying an uninitialized/unsupported boolean template.");
798 set_selection(other_value
);
801 BOOLEAN_template::BOOLEAN_template()
806 BOOLEAN_template::BOOLEAN_template(template_sel other_value
)
807 : Base_Template(other_value
)
809 check_single_selection(other_value
);
812 BOOLEAN_template::BOOLEAN_template(boolean other_value
)
813 : Base_Template(SPECIFIC_VALUE
)
815 single_value
= other_value
;
818 BOOLEAN_template::BOOLEAN_template(const BOOLEAN
& other_value
)
819 : Base_Template(SPECIFIC_VALUE
)
821 other_value
.must_bound("Creating a template from an unbound integer value.");
822 single_value
= other_value
.boolean_value
;
825 BOOLEAN_template::BOOLEAN_template(const OPTIONAL
<BOOLEAN
>& other_value
)
827 switch (other_value
.get_selection()) {
828 case OPTIONAL_PRESENT
:
829 set_selection(SPECIFIC_VALUE
);
830 single_value
= (boolean
)(const BOOLEAN
&)other_value
;
833 set_selection(OMIT_VALUE
);
836 TTCN_error("Creating a boolean template from an unbound optional field.");
840 BOOLEAN_template::BOOLEAN_template(const BOOLEAN_template
& other_value
)
843 copy_template(other_value
);
846 BOOLEAN_template::~BOOLEAN_template()
851 BOOLEAN_template
& BOOLEAN_template::operator=(template_sel other_value
)
853 check_single_selection(other_value
);
855 set_selection(other_value
);
859 BOOLEAN_template
& BOOLEAN_template::operator=(boolean other_value
)
862 set_selection(SPECIFIC_VALUE
);
863 single_value
= other_value
;
867 BOOLEAN_template
& BOOLEAN_template::operator=(const BOOLEAN
& other_value
)
869 other_value
.must_bound("Assignment of an unbound boolean value to a "
872 set_selection(SPECIFIC_VALUE
);
873 single_value
= other_value
.boolean_value
;
877 BOOLEAN_template
& BOOLEAN_template::operator=
878 (const OPTIONAL
<BOOLEAN
>& other_value
)
881 switch (other_value
.get_selection()) {
882 case OPTIONAL_PRESENT
:
883 set_selection(SPECIFIC_VALUE
);
884 single_value
= (boolean
)(const BOOLEAN
&)other_value
;
887 set_selection(OMIT_VALUE
);
890 TTCN_error("Assignment of an unbound optional field to a boolean "
896 BOOLEAN_template
& BOOLEAN_template::operator=
897 (const BOOLEAN_template
& other_value
)
899 if (&other_value
!= this) {
901 copy_template(other_value
);
906 boolean
BOOLEAN_template::match(boolean other_value
) const
908 switch (template_selection
) {
910 return single_value
== other_value
;
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
;
923 TTCN_error("Matching with an uninitialized/unsupported boolean template.");
928 boolean
BOOLEAN_template::match(const BOOLEAN
& other_value
) const
930 if (!other_value
.is_bound()) return FALSE
;
931 return match(other_value
.boolean_value
);
934 boolean
BOOLEAN_template::valueof() const
936 if (template_selection
!= SPECIFIC_VALUE
|| is_ifpresent
)
937 TTCN_error("Performing valueof or "
938 "send operation on a non-specific boolean template.");
942 void BOOLEAN_template::set_type(template_sel template_type
,
943 unsigned int list_length
)
945 if (template_type
!= VALUE_LIST
&& template_type
!= COMPLEMENTED_LIST
)
946 TTCN_error("Setting an invalid list type for a boolean template.");
948 set_selection(template_type
);
949 value_list
.n_values
= list_length
;
950 value_list
.list_value
= new BOOLEAN_template
[list_length
];
953 BOOLEAN_template
& BOOLEAN_template::list_item(unsigned int list_index
)
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
];
963 void BOOLEAN_template::log() const
965 switch (template_selection
) {
967 TTCN_Logger::log_event_str(single_value
? "true" : "false");
969 case COMPLEMENTED_LIST
:
970 TTCN_Logger::log_event_str("complement ");
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();
978 TTCN_Logger::log_char(')');
987 void BOOLEAN_template::log_match(const BOOLEAN
& match_value
) const
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(" := ");
995 TTCN_Logger::log_event_str(" with ");
997 if (match(match_value
)) TTCN_Logger::log_event_str(" matched");
998 else TTCN_Logger::log_event_str(" unmatched");
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
:
1007 case Module_Param::MP_Any
:
1010 case Module_Param::MP_AnyOrNone
:
1011 *this = ANY_OR_OMIT
;
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
));
1020 case Module_Param::MP_Boolean
:
1021 *this = param
.get_boolean();
1024 param
.type_error("boolean template");
1026 is_ifpresent
= param
.get_ifpresent();
1029 void BOOLEAN_template::encode_text(Text_Buf
& text_buf
) const
1031 encode_text_base(text_buf
);
1032 switch (template_selection
) {
1037 case SPECIFIC_VALUE
:
1038 text_buf
.push_int(single_value
? 1 : 0);
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
);
1047 TTCN_error("Text encoder: Encoding an uninitialized/unsupported boolean "
1052 void BOOLEAN_template::decode_text(Text_Buf
& text_buf
)
1055 decode_text_base(text_buf
);
1056 switch (template_selection
) {
1061 case SPECIFIC_VALUE
: {
1062 int int_value
= text_buf
.pull_int().get_val();
1063 switch (int_value
) {
1065 single_value
= FALSE
;
1068 single_value
= TRUE
;
1071 TTCN_error("Text decoder: An invalid boolean value (%d) was received for "
1072 "a template.", int_value
);
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
);
1083 TTCN_error("Text decoder: An unknown/unsupported selection was "
1084 "received for a boolean template.");
1088 boolean
BOOLEAN_template::is_present() const
1090 if (template_selection
==UNINITIALIZED_TEMPLATE
) return FALSE
;
1091 return !match_omit();
1094 boolean
BOOLEAN_template::match_omit() const
1096 if (is_ifpresent
) return TRUE
;
1097 switch (template_selection
) {
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
;
1113 #ifndef TITAN_RUNTIME_2
1114 void BOOLEAN_template::check_restriction(template_res t_res
, const char* t_name
) const
1116 if (template_selection
==UNINITIALIZED_TEMPLATE
) return;
1117 switch ((t_name
&&(t_res
==TR_VALUE
))?TR_OMIT
:t_res
) {
1119 if (!is_ifpresent
&& template_selection
==SPECIFIC_VALUE
) return;
1122 if (!is_ifpresent
&& (template_selection
==OMIT_VALUE
||
1123 template_selection
==SPECIFIC_VALUE
)) return;
1126 if (!match_omit()) return;
1131 TTCN_error("Restriction `%s' on template of type %s violated.",
1132 get_res_name(t_res
), t_name
? t_name
: "boolean");