1 ///////////////////////////////////////////////////////////////////////////////
2 // Copyright (c) 2000-2015 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 ///////////////////////////////////////////////////////////////////////////////
10 #include "ASN_Null.hh"
11 #include "Parameters.h"
12 #include "Param_Types.hh"
18 #include "../common/dbgnew.hh"
25 ASN_NULL::ASN_NULL(asn_null_type
)
30 ASN_NULL::ASN_NULL(const ASN_NULL
& other_value
)
31 : Base_Type(other_value
)
33 if (!other_value
.bound_flag
)
34 TTCN_error("Copying an unbound ASN.1 NULL value.");
38 ASN_NULL
& ASN_NULL::operator=(asn_null_type
)
44 ASN_NULL
& ASN_NULL::operator=(const ASN_NULL
& other_value
)
46 if (!other_value
.bound_flag
)
47 TTCN_error("Assignment of an unbound ASN.1 NULL value.");
52 boolean
ASN_NULL::operator==(asn_null_type
) const
54 if (!bound_flag
) TTCN_error("The left operand of comparison is an unbound "
59 boolean
ASN_NULL::operator==(const ASN_NULL
& other_value
) const
61 if (!bound_flag
) TTCN_error("The left operand of comparison is an unbound "
63 if (!other_value
.bound_flag
) TTCN_error("The right operand of comparison "
64 "is an unbound ASN.1 NULL value.");
68 void ASN_NULL::log() const
70 if (bound_flag
) TTCN_Logger::log_event_str("NULL");
71 else TTCN_Logger::log_event_unbound();
74 void ASN_NULL::set_param(Module_Param
& param
) {
75 param
.basic_check(Module_Param::BC_VALUE
, "NULL value");
76 Module_Param_Ptr mp
= ¶m
;
77 if (param
.get_type() == Module_Param::MP_Reference
) {
78 mp
= param
.get_referenced_param();
80 if (mp
->get_type()!=Module_Param::MP_Asn_Null
) param
.type_error("NULL value");
84 Module_Param
* ASN_NULL::get_param(Module_Param_Name
& /* param_name */) const
87 return new Module_Param_Unbound();
89 return new Module_Param_Asn_Null();
92 void ASN_NULL::encode_text(Text_Buf
&) const
95 TTCN_error("Text encoder: Encoding an unbound ASN.1 NULL value.");
98 void ASN_NULL::decode_text(Text_Buf
&)
103 void ASN_NULL::encode(const TTCN_Typedescriptor_t
& p_td
, TTCN_Buffer
& p_buf
,
104 TTCN_EncDec::coding_t p_coding
, ...) const
107 va_start(pvar
, p_coding
);
109 case TTCN_EncDec::CT_BER
: {
110 TTCN_EncDec_ErrorContext
ec("While BER-encoding type '%s': ", p_td
.name
);
111 unsigned BER_coding
=va_arg(pvar
, unsigned);
112 BER_encode_chk_coding(BER_coding
);
113 ASN_BER_TLV_t
*tlv
=BER_encode_TLV(p_td
, BER_coding
);
114 tlv
->put_in_buffer(p_buf
);
115 ASN_BER_TLV_t::destruct(tlv
);
117 case TTCN_EncDec::CT_XER
: {
118 TTCN_EncDec_ErrorContext
ec("While XER-encoding type '%s': ", p_td
.name
);
119 unsigned XER_coding
=va_arg(pvar
, unsigned);
120 XER_encode(*p_td
.xer
, p_buf
, XER_coding
, 0, 0);
122 case TTCN_EncDec::CT_JSON
: {
123 TTCN_EncDec_ErrorContext
ec("While JSON-encoding type '%s': ", p_td
.name
);
125 TTCN_EncDec_ErrorContext::error_internal
126 ("No JSON descriptor available for type '%s'.", p_td
.name
);
127 JSON_Tokenizer
tok(va_arg(pvar
, int) != 0);
128 JSON_encode(p_td
, tok
);
129 p_buf
.put_s(tok
.get_buffer_length(), (const unsigned char*)tok
.get_buffer());
131 case TTCN_EncDec::CT_RAW
:
133 TTCN_error("Unknown coding method requested to encode type '%s'",
139 void ASN_NULL::decode(const TTCN_Typedescriptor_t
& p_td
, TTCN_Buffer
& p_buf
,
140 TTCN_EncDec::coding_t p_coding
, ...)
143 va_start(pvar
, p_coding
);
145 case TTCN_EncDec::CT_BER
: {
146 TTCN_EncDec_ErrorContext
ec("While BER-decoding type '%s': ", p_td
.name
);
147 unsigned L_form
=va_arg(pvar
, unsigned);
149 BER_decode_str2TLV(p_buf
, tlv
, L_form
);
150 BER_decode_TLV(p_td
, tlv
, L_form
);
151 if(tlv
.isComplete
) p_buf
.increase_pos(tlv
.get_len());
153 case TTCN_EncDec::CT_XER
: {
154 TTCN_EncDec_ErrorContext
ec("While XER-decoding type '%s': ", p_td
.name
);
155 unsigned XER_coding
=va_arg(pvar
, unsigned);
156 XmlReaderWrap
reader(p_buf
);
157 int success
= reader
.Read();
158 for (; success
==1; success
=reader
.Read()) {
159 int type
= reader
.NodeType();
160 if (type
==XML_READER_TYPE_ELEMENT
)
163 XER_decode(*p_td
.xer
, reader
, XER_coding
, 0);
164 size_t bytes
= reader
.ByteConsumed();
165 p_buf
.set_pos(bytes
);
167 case TTCN_EncDec::CT_JSON
: {
168 TTCN_EncDec_ErrorContext
ec("While JSON-decoding type '%s': ", p_td
.name
);
170 TTCN_EncDec_ErrorContext::error_internal
171 ("No JSON descriptor available for type '%s'.", p_td
.name
);
172 JSON_Tokenizer
tok((const char*)p_buf
.get_data(), p_buf
.get_len());
173 if(JSON_decode(p_td
, tok
, false)<0)
174 ec
.error(TTCN_EncDec::ET_INCOMPL_MSG
,
175 "Can not decode type '%s', because invalid or incomplete"
176 " message was received"
178 p_buf
.set_pos(tok
.get_buf_pos());
180 case TTCN_EncDec::CT_RAW
:
182 TTCN_error("Unknown coding method requested to decode type '%s'",
189 ASN_NULL::BER_encode_TLV(const TTCN_Typedescriptor_t
& p_td
,
190 unsigned p_coding
) const
193 ASN_BER_TLV_t
*new_tlv
=BER_encode_chk_bound(is_bound());
195 new_tlv
=ASN_BER_TLV_t::construct(0, NULL
);
197 new_tlv
=ASN_BER_V2TLV(new_tlv
, p_td
, p_coding
);
201 boolean
ASN_NULL::BER_decode_TLV(const TTCN_Typedescriptor_t
& p_td
,
202 const ASN_BER_TLV_t
& p_tlv
,
207 ASN_BER_TLV_t stripped_tlv
;
208 BER_decode_strip_tags(*p_td
.ber
, p_tlv
, L_form
, stripped_tlv
);
209 TTCN_EncDec_ErrorContext
ec("While decoding NULL type: ");
210 stripped_tlv
.chk_constructed_flag(FALSE
);
211 if(!stripped_tlv
.V_tlvs_selected
&& stripped_tlv
.V
.str
.Vlen
!=0)
212 ec
.error(TTCN_EncDec::ET_INVAL_MSG
, "Length of V-part is not 0.");
217 int ASN_NULL::XER_encode(const XERdescriptor_t
& p_td
,
218 TTCN_Buffer
& p_buf
, unsigned int flavor
, int indent
, embed_values_enc_struct_t
*) const
220 int exer
= is_exer(flavor
);
221 TTCN_EncDec_ErrorContext
ec("While XER encoding NULL type: ");
223 TTCN_EncDec_ErrorContext::error
224 (TTCN_EncDec::ET_UNBOUND
, "Encoding an unbound ASN.1 NULL value.");
227 int indenting
= !is_canonical(flavor
) && !is_record_of(flavor
);
228 int encoded_length
=(int)p_buf
.get_len();
230 if (indenting
) do_indent(p_buf
, indent
);
234 if (exer
) write_ns_prefix(p_td
, p_buf
);
235 p_buf
.put_s((size_t)p_td
.namelens
[exer
]-2, (const unsigned char*)p_td
.names
[exer
]);
237 p_buf
.put_s(2 + indenting
, (const unsigned char*)"/>\n");
238 return (int)p_buf
.get_len() - encoded_length
;
241 int ASN_NULL::XER_decode(const XERdescriptor_t
& p_td
, XmlReaderWrap
& reader
,
242 unsigned int flavor
, embed_values_dec_struct_t
*)
244 int exer
= is_exer(flavor
);
245 TTCN_EncDec_ErrorContext
ec("While XER decoding NULL type: ");
246 int success
= reader
.Ok(), depth
= -1;
247 for (; success
== 1; success
= reader
.Read()) {
248 int type
= reader
.NodeType();
249 if (XML_READER_TYPE_ELEMENT
== type
) {
250 verify_name(reader
, p_td
, exer
);
251 depth
= reader
.Depth();
256 int gol
= reader
.IsEmptyElement();
257 if (!gol
) { // shouldn't happen
258 for (success
= reader
.Read(); success
== 1; success
= reader
.Read()) {
259 int type
= reader
.NodeType();
260 if (XML_READER_TYPE_END_ELEMENT
== type
) {
261 verify_end(reader
, p_td
, depth
, exer
);
262 // FIXME reader.Read() ??
269 return 1; // decode successful
272 int ASN_NULL::JSON_encode(const TTCN_Typedescriptor_t
&, JSON_Tokenizer
& p_tok
) const
275 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND
,
276 "Encoding an unbound ASN.1 NULL value.");
280 return p_tok
.put_next_token(JSON_TOKEN_LITERAL_NULL
);
283 int ASN_NULL::JSON_decode(const TTCN_Typedescriptor_t
&, JSON_Tokenizer
& p_tok
, boolean p_silent
)
285 json_token_t token
= JSON_TOKEN_NONE
;
286 int dec_len
= p_tok
.get_next_token(&token
, NULL
, NULL
);
287 if (JSON_TOKEN_ERROR
== token
) {
288 JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG
, JSON_DEC_BAD_TOKEN_ERROR
, "");
289 return JSON_ERROR_FATAL
;
291 else if (JSON_TOKEN_LITERAL_NULL
!= token
) {
292 return JSON_ERROR_INVALID_TOKEN
;
298 boolean
operator==(asn_null_type
, const ASN_NULL
& other_value
)
300 if (!other_value
.is_bound()) TTCN_error("The right operand of comparison "
301 "is an unbound ASN.1 NULL value.");
305 void ASN_NULL_template::clean_up()
307 if (template_selection
== VALUE_LIST
||
308 template_selection
== COMPLEMENTED_LIST
) delete [] value_list
.list_value
;
309 template_selection
= UNINITIALIZED_TEMPLATE
;
312 void ASN_NULL_template::copy_template(const ASN_NULL_template
& other_value
)
314 switch (other_value
.template_selection
) {
321 case COMPLEMENTED_LIST
:
322 value_list
.n_values
= other_value
.value_list
.n_values
;
323 value_list
.list_value
= new ASN_NULL_template
[value_list
.n_values
];
324 for (unsigned int i
= 0; i
< value_list
.n_values
; i
++)
325 value_list
.list_value
[i
].copy_template(
326 other_value
.value_list
.list_value
[i
]);
329 TTCN_error("Copying an uninitialized/unsupported template of ASN.1 "
332 set_selection(other_value
);
335 ASN_NULL_template::ASN_NULL_template()
340 ASN_NULL_template::ASN_NULL_template(template_sel other_value
)
341 : Base_Template(other_value
)
343 check_single_selection(other_value
);
346 ASN_NULL_template::ASN_NULL_template(asn_null_type
)
347 : Base_Template(SPECIFIC_VALUE
)
352 ASN_NULL_template::ASN_NULL_template(const ASN_NULL
& other_value
)
353 : Base_Template(SPECIFIC_VALUE
)
355 if (!other_value
.is_bound())
356 TTCN_error("Creating a template from an unbound ASN.1 NULL value.");
359 ASN_NULL_template::ASN_NULL_template(const OPTIONAL
<ASN_NULL
>& other_value
)
361 switch (other_value
.get_selection()) {
362 case OPTIONAL_PRESENT
:
363 set_selection(SPECIFIC_VALUE
);
366 set_selection(OMIT_VALUE
);
369 TTCN_error("Creating a template of ASN.1 NULL type from an unbound "
374 ASN_NULL_template::ASN_NULL_template(const ASN_NULL_template
& other_value
)
377 copy_template(other_value
);
380 ASN_NULL_template::~ASN_NULL_template()
385 ASN_NULL_template
& ASN_NULL_template::operator=(template_sel other_value
)
387 check_single_selection(other_value
);
389 set_selection(other_value
);
393 ASN_NULL_template
& ASN_NULL_template::operator=(asn_null_type
)
396 set_selection(SPECIFIC_VALUE
);
400 ASN_NULL_template
& ASN_NULL_template::operator=(const ASN_NULL
& other_value
)
402 if (!other_value
.is_bound()) TTCN_error("Assignment of an unbound ASN.1 "
403 "NULL value to a template.");
405 set_selection(SPECIFIC_VALUE
);
409 ASN_NULL_template
& ASN_NULL_template::operator=
410 (const OPTIONAL
<ASN_NULL
>& other_value
)
413 switch (other_value
.get_selection()) {
414 case OPTIONAL_PRESENT
:
415 set_selection(SPECIFIC_VALUE
);
418 set_selection(OMIT_VALUE
);
421 TTCN_error("Assignment of an unbound optional field to a template of "
427 ASN_NULL_template
& ASN_NULL_template::operator=
428 (const ASN_NULL_template
& other_value
)
430 if (&other_value
!= this) {
432 copy_template(other_value
);
437 boolean
ASN_NULL_template::match(asn_null_type other_value
,
438 boolean
/* legacy */) const
440 switch (template_selection
) {
448 case COMPLEMENTED_LIST
:
449 for (unsigned int i
= 0; i
< value_list
.n_values
; i
++)
450 if (value_list
.list_value
[i
].match(other_value
))
451 return template_selection
== VALUE_LIST
;
452 return template_selection
== COMPLEMENTED_LIST
;
454 TTCN_error("Matching with an uninitialized/unsupported template of "
460 boolean
ASN_NULL_template::match(const ASN_NULL
& other_value
,
461 boolean
/* legacy */) const
463 if (!other_value
.is_bound()) return FALSE
;
464 return match(ASN_NULL_VALUE
);
467 asn_null_type
ASN_NULL_template::valueof() const
469 if (template_selection
!= SPECIFIC_VALUE
|| is_ifpresent
)
470 TTCN_error("Performing a valueof "
471 "or send operation on a non-specific template of ASN.1 NULL type.");
472 return ASN_NULL_VALUE
;
475 void ASN_NULL_template::set_type(template_sel template_type
,
476 unsigned int list_length
)
478 if (template_type
!= VALUE_LIST
&& template_type
!= COMPLEMENTED_LIST
)
479 TTCN_error("Setting an invalid list type for a template of ASN.1 NULL "
482 set_selection(template_type
);
483 value_list
.n_values
= list_length
;
484 value_list
.list_value
= new ASN_NULL_template
[list_length
];
487 ASN_NULL_template
& ASN_NULL_template::list_item(unsigned int list_index
)
489 if (template_selection
!= VALUE_LIST
&&
490 template_selection
!= COMPLEMENTED_LIST
) TTCN_error("Accessing a list "
491 "element of a non-list template for ASN.1 NULL type.");
492 if (list_index
>= value_list
.n_values
)
493 TTCN_error("Index overflow in a value list template of ASN.1 NULL type.");
494 return value_list
.list_value
[list_index
];
497 void ASN_NULL_template::log() const
499 switch (template_selection
) {
501 TTCN_Logger::log_event_str("NULL");
503 case COMPLEMENTED_LIST
:
504 TTCN_Logger::log_event_str("complement ");
506 TTCN_Logger::log_char('(');
507 for (unsigned int i
= 0; i
< value_list
.n_values
; i
++) {
508 if (i
> 0) TTCN_Logger::log_event_str(", ");
509 value_list
.list_value
[i
].log();
511 TTCN_Logger::log_char(')');
519 void ASN_NULL_template::log_match(const ASN_NULL
& match_value
,
520 boolean
/* legacy */) const
522 if(TTCN_Logger::VERBOSITY_COMPACT
== TTCN_Logger::get_matching_verbosity()){
523 TTCN_Logger::print_logmatch_buffer();
524 TTCN_Logger::log_event_str(" := ");
527 TTCN_Logger::log_event_str(" with ");
529 if (match(match_value
)) TTCN_Logger::log_event_str(" matched");
530 else TTCN_Logger::log_event_str(" unmatched");
533 void ASN_NULL_template::set_param(Module_Param
& param
) {
534 param
.basic_check(Module_Param::BC_TEMPLATE
, "NULL template");
535 Module_Param_Ptr mp
= ¶m
;
536 if (param
.get_type() == Module_Param::MP_Reference
) {
537 mp
= param
.get_referenced_param();
539 switch (mp
->get_type()) {
540 case Module_Param::MP_Omit
:
543 case Module_Param::MP_Any
:
546 case Module_Param::MP_AnyOrNone
:
549 case Module_Param::MP_List_Template
:
550 case Module_Param::MP_ComplementList_Template
: {
551 ASN_NULL_template temp
;
552 temp
.set_type(mp
->get_type() == Module_Param::MP_List_Template
?
553 VALUE_LIST
: COMPLEMENTED_LIST
, mp
->get_size());
554 for (size_t i
=0; i
<mp
->get_size(); i
++) {
555 temp
.list_item(i
).set_param(*mp
->get_elem(i
));
559 case Module_Param::MP_Asn_Null
:
560 *this = ASN_NULL_VALUE
;
563 param
.type_error("NULL template");
565 is_ifpresent
= param
.get_ifpresent() || mp
->get_ifpresent();
568 Module_Param
* ASN_NULL_template::get_param(Module_Param_Name
& param_name
) const
570 Module_Param
* mp
= NULL
;
571 switch (template_selection
) {
572 case UNINITIALIZED_TEMPLATE
:
573 mp
= new Module_Param_Unbound();
576 mp
= new Module_Param_Omit();
579 mp
= new Module_Param_Any();
582 mp
= new Module_Param_AnyOrNone();
585 mp
= new Module_Param_Asn_Null();
588 case COMPLEMENTED_LIST
: {
589 if (template_selection
== VALUE_LIST
) {
590 mp
= new Module_Param_List_Template();
593 mp
= new Module_Param_ComplementList_Template();
595 for (size_t i
= 0; i
< value_list
.n_values
; ++i
) {
596 mp
->add_elem(value_list
.list_value
[i
].get_param(param_name
));
608 void ASN_NULL_template::encode_text(Text_Buf
& text_buf
) const
610 encode_text_base(text_buf
);
611 switch (template_selection
) {
618 case COMPLEMENTED_LIST
:
619 text_buf
.push_int(value_list
.n_values
);
620 for (unsigned int i
= 0; i
< value_list
.n_values
; i
++)
621 value_list
.list_value
[i
].encode_text(text_buf
);
624 TTCN_error("Text encoder: Encoding an undefined/unsupported template "
625 "of ASN.1 NULL type.");
629 void ASN_NULL_template::decode_text(Text_Buf
& text_buf
)
632 decode_text_base(text_buf
);
633 switch (template_selection
) {
640 case COMPLEMENTED_LIST
:
641 value_list
.n_values
= text_buf
.pull_int().get_val();
642 value_list
.list_value
= new ASN_NULL_template
[value_list
.n_values
];
643 for (unsigned int i
= 0; i
< value_list
.n_values
; i
++)
644 value_list
.list_value
[i
].decode_text(text_buf
);
647 TTCN_error("Text decoder: An unknown/unsupported selection was received "
648 "in a template for ASN.1 NULL type.");
652 boolean
ASN_NULL_template::is_present(boolean legacy
/* = FALSE */) const
654 if (template_selection
==UNINITIALIZED_TEMPLATE
) return FALSE
;
655 return !match_omit(legacy
);
658 boolean
ASN_NULL_template::match_omit(boolean legacy
/* = FALSE */) const
660 if (is_ifpresent
) return TRUE
;
661 switch (template_selection
) {
666 case COMPLEMENTED_LIST
:
668 // legacy behavior: 'omit' can appear in the value/complement list
669 for (unsigned int i
=0; i
<value_list
.n_values
; i
++)
670 if (value_list
.list_value
[i
].match_omit())
671 return template_selection
==VALUE_LIST
;
672 return template_selection
==COMPLEMENTED_LIST
;
681 #ifndef TITAN_RUNTIME_2
682 void ASN_NULL_template::check_restriction(template_res t_res
, const char* t_name
,
683 boolean legacy
/* = FALSE */) const
685 if (template_selection
==UNINITIALIZED_TEMPLATE
) return;
686 switch ((t_name
&&(t_res
==TR_VALUE
))?TR_OMIT
:t_res
) {
688 if (!is_ifpresent
&& template_selection
==SPECIFIC_VALUE
) return;
691 if (!is_ifpresent
&& (template_selection
==OMIT_VALUE
||
692 template_selection
==SPECIFIC_VALUE
)) return;
695 if (!match_omit(legacy
)) return;
700 TTCN_error("Restriction `%s' on template of type %s violated.",
701 get_res_name(t_res
), t_name
? t_name
: "ASN.1 NULL");