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
18 * Szabo, Janos Zoltan – initial implementation
22 ******************************************************************************/
25 #include "ASN_Null.hh"
26 #include "Parameters.h"
27 #include "Param_Types.hh"
33 #include "../common/dbgnew.hh"
40 ASN_NULL::ASN_NULL(asn_null_type
)
45 ASN_NULL::ASN_NULL(const ASN_NULL
& other_value
)
46 : Base_Type(other_value
)
48 if (!other_value
.bound_flag
)
49 TTCN_error("Copying an unbound ASN.1 NULL value.");
53 ASN_NULL
& ASN_NULL::operator=(asn_null_type
)
59 ASN_NULL
& ASN_NULL::operator=(const ASN_NULL
& other_value
)
61 if (!other_value
.bound_flag
)
62 TTCN_error("Assignment of an unbound ASN.1 NULL value.");
67 boolean
ASN_NULL::operator==(asn_null_type
) const
69 if (!bound_flag
) TTCN_error("The left operand of comparison is an unbound "
74 boolean
ASN_NULL::operator==(const ASN_NULL
& other_value
) const
76 if (!bound_flag
) TTCN_error("The left operand of comparison is an unbound "
78 if (!other_value
.bound_flag
) TTCN_error("The right operand of comparison "
79 "is an unbound ASN.1 NULL value.");
83 void ASN_NULL::log() const
85 if (bound_flag
) TTCN_Logger::log_event_str("NULL");
86 else TTCN_Logger::log_event_unbound();
89 void ASN_NULL::set_param(Module_Param
& param
) {
90 param
.basic_check(Module_Param::BC_VALUE
, "NULL value");
91 Module_Param_Ptr mp
= ¶m
;
92 if (param
.get_type() == Module_Param::MP_Reference
) {
93 mp
= param
.get_referenced_param();
95 if (mp
->get_type()!=Module_Param::MP_Asn_Null
) param
.type_error("NULL value");
99 Module_Param
* ASN_NULL::get_param(Module_Param_Name
& /* param_name */) const
102 return new Module_Param_Unbound();
104 return new Module_Param_Asn_Null();
107 void ASN_NULL::encode_text(Text_Buf
&) const
110 TTCN_error("Text encoder: Encoding an unbound ASN.1 NULL value.");
113 void ASN_NULL::decode_text(Text_Buf
&)
118 void ASN_NULL::encode(const TTCN_Typedescriptor_t
& p_td
, TTCN_Buffer
& p_buf
,
119 TTCN_EncDec::coding_t p_coding
, ...) const
122 va_start(pvar
, p_coding
);
124 case TTCN_EncDec::CT_BER
: {
125 TTCN_EncDec_ErrorContext
ec("While BER-encoding type '%s': ", p_td
.name
);
126 unsigned BER_coding
=va_arg(pvar
, unsigned);
127 BER_encode_chk_coding(BER_coding
);
128 ASN_BER_TLV_t
*tlv
=BER_encode_TLV(p_td
, BER_coding
);
129 tlv
->put_in_buffer(p_buf
);
130 ASN_BER_TLV_t::destruct(tlv
);
132 case TTCN_EncDec::CT_XER
: {
133 TTCN_EncDec_ErrorContext
ec("While XER-encoding type '%s': ", p_td
.name
);
134 unsigned XER_coding
=va_arg(pvar
, unsigned);
135 XER_encode(*p_td
.xer
, p_buf
, XER_coding
, 0, 0);
137 case TTCN_EncDec::CT_JSON
: {
138 TTCN_EncDec_ErrorContext
ec("While JSON-encoding type '%s': ", p_td
.name
);
140 TTCN_EncDec_ErrorContext::error_internal
141 ("No JSON descriptor available for type '%s'.", p_td
.name
);
142 JSON_Tokenizer
tok(va_arg(pvar
, int) != 0);
143 JSON_encode(p_td
, tok
);
144 p_buf
.put_s(tok
.get_buffer_length(), (const unsigned char*)tok
.get_buffer());
146 case TTCN_EncDec::CT_RAW
:
148 TTCN_error("Unknown coding method requested to encode type '%s'",
154 void ASN_NULL::decode(const TTCN_Typedescriptor_t
& p_td
, TTCN_Buffer
& p_buf
,
155 TTCN_EncDec::coding_t p_coding
, ...)
158 va_start(pvar
, p_coding
);
160 case TTCN_EncDec::CT_BER
: {
161 TTCN_EncDec_ErrorContext
ec("While BER-decoding type '%s': ", p_td
.name
);
162 unsigned L_form
=va_arg(pvar
, unsigned);
164 BER_decode_str2TLV(p_buf
, tlv
, L_form
);
165 BER_decode_TLV(p_td
, tlv
, L_form
);
166 if(tlv
.isComplete
) p_buf
.increase_pos(tlv
.get_len());
168 case TTCN_EncDec::CT_XER
: {
169 TTCN_EncDec_ErrorContext
ec("While XER-decoding type '%s': ", p_td
.name
);
170 unsigned XER_coding
=va_arg(pvar
, unsigned);
171 XmlReaderWrap
reader(p_buf
);
172 int success
= reader
.Read();
173 for (; success
==1; success
=reader
.Read()) {
174 int type
= reader
.NodeType();
175 if (type
==XML_READER_TYPE_ELEMENT
)
178 XER_decode(*p_td
.xer
, reader
, XER_coding
, XER_NONE
, 0);
179 size_t bytes
= reader
.ByteConsumed();
180 p_buf
.set_pos(bytes
);
182 case TTCN_EncDec::CT_JSON
: {
183 TTCN_EncDec_ErrorContext
ec("While JSON-decoding type '%s': ", p_td
.name
);
185 TTCN_EncDec_ErrorContext::error_internal
186 ("No JSON descriptor available for type '%s'.", p_td
.name
);
187 JSON_Tokenizer
tok((const char*)p_buf
.get_data(), p_buf
.get_len());
188 if(JSON_decode(p_td
, tok
, false)<0)
189 ec
.error(TTCN_EncDec::ET_INCOMPL_MSG
,
190 "Can not decode type '%s', because invalid or incomplete"
191 " message was received"
193 p_buf
.set_pos(tok
.get_buf_pos());
195 case TTCN_EncDec::CT_RAW
:
197 TTCN_error("Unknown coding method requested to decode type '%s'",
204 ASN_NULL::BER_encode_TLV(const TTCN_Typedescriptor_t
& p_td
,
205 unsigned p_coding
) const
208 ASN_BER_TLV_t
*new_tlv
=BER_encode_chk_bound(is_bound());
210 new_tlv
=ASN_BER_TLV_t::construct(0, NULL
);
212 new_tlv
=ASN_BER_V2TLV(new_tlv
, p_td
, p_coding
);
216 boolean
ASN_NULL::BER_decode_TLV(const TTCN_Typedescriptor_t
& p_td
,
217 const ASN_BER_TLV_t
& p_tlv
,
222 ASN_BER_TLV_t stripped_tlv
;
223 BER_decode_strip_tags(*p_td
.ber
, p_tlv
, L_form
, stripped_tlv
);
224 TTCN_EncDec_ErrorContext
ec("While decoding NULL type: ");
225 stripped_tlv
.chk_constructed_flag(FALSE
);
226 if(!stripped_tlv
.V_tlvs_selected
&& stripped_tlv
.V
.str
.Vlen
!=0)
227 ec
.error(TTCN_EncDec::ET_INVAL_MSG
, "Length of V-part is not 0.");
232 int ASN_NULL::XER_encode(const XERdescriptor_t
& p_td
,
233 TTCN_Buffer
& p_buf
, unsigned int flavor
, int indent
, embed_values_enc_struct_t
*) const
235 int exer
= is_exer(flavor
);
236 TTCN_EncDec_ErrorContext
ec("While XER encoding NULL type: ");
238 TTCN_EncDec_ErrorContext::error
239 (TTCN_EncDec::ET_UNBOUND
, "Encoding an unbound ASN.1 NULL value.");
242 int indenting
= !is_canonical(flavor
) && !is_record_of(flavor
);
243 int encoded_length
=(int)p_buf
.get_len();
245 if (indenting
) do_indent(p_buf
, indent
);
249 if (exer
) write_ns_prefix(p_td
, p_buf
);
250 p_buf
.put_s((size_t)p_td
.namelens
[exer
]-2, (const unsigned char*)p_td
.names
[exer
]);
252 p_buf
.put_s(2 + indenting
, (const unsigned char*)"/>\n");
253 return (int)p_buf
.get_len() - encoded_length
;
256 int ASN_NULL::XER_decode(const XERdescriptor_t
& p_td
, XmlReaderWrap
& reader
,
257 unsigned int flavor
, unsigned int /*flavor2*/, embed_values_dec_struct_t
*)
259 int exer
= is_exer(flavor
);
260 TTCN_EncDec_ErrorContext
ec("While XER decoding NULL type: ");
261 int success
= reader
.Ok(), depth
= -1;
262 for (; success
== 1; success
= reader
.Read()) {
263 int type
= reader
.NodeType();
264 if (XML_READER_TYPE_ELEMENT
== type
) {
265 verify_name(reader
, p_td
, exer
);
266 depth
= reader
.Depth();
271 int gol
= reader
.IsEmptyElement();
272 if (!gol
) { // shouldn't happen
273 for (success
= reader
.Read(); success
== 1; success
= reader
.Read()) {
274 int type
= reader
.NodeType();
275 if (XML_READER_TYPE_END_ELEMENT
== type
) {
276 verify_end(reader
, p_td
, depth
, exer
);
277 // FIXME reader.Read() ??
284 return 1; // decode successful
287 int ASN_NULL::JSON_encode(const TTCN_Typedescriptor_t
&, JSON_Tokenizer
& p_tok
) const
290 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND
,
291 "Encoding an unbound ASN.1 NULL value.");
295 return p_tok
.put_next_token(JSON_TOKEN_LITERAL_NULL
);
298 int ASN_NULL::JSON_decode(const TTCN_Typedescriptor_t
&, JSON_Tokenizer
& p_tok
, boolean p_silent
)
300 json_token_t token
= JSON_TOKEN_NONE
;
301 int dec_len
= p_tok
.get_next_token(&token
, NULL
, NULL
);
302 if (JSON_TOKEN_ERROR
== token
) {
303 JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG
, JSON_DEC_BAD_TOKEN_ERROR
, "");
304 return JSON_ERROR_FATAL
;
306 else if (JSON_TOKEN_LITERAL_NULL
!= token
) {
307 return JSON_ERROR_INVALID_TOKEN
;
313 boolean
operator==(asn_null_type
, const ASN_NULL
& other_value
)
315 if (!other_value
.is_bound()) TTCN_error("The right operand of comparison "
316 "is an unbound ASN.1 NULL value.");
320 void ASN_NULL_template::clean_up()
322 if (template_selection
== VALUE_LIST
||
323 template_selection
== COMPLEMENTED_LIST
) delete [] value_list
.list_value
;
324 template_selection
= UNINITIALIZED_TEMPLATE
;
327 void ASN_NULL_template::copy_template(const ASN_NULL_template
& other_value
)
329 switch (other_value
.template_selection
) {
336 case COMPLEMENTED_LIST
:
337 value_list
.n_values
= other_value
.value_list
.n_values
;
338 value_list
.list_value
= new ASN_NULL_template
[value_list
.n_values
];
339 for (unsigned int i
= 0; i
< value_list
.n_values
; i
++)
340 value_list
.list_value
[i
].copy_template(
341 other_value
.value_list
.list_value
[i
]);
344 TTCN_error("Copying an uninitialized/unsupported template of ASN.1 "
347 set_selection(other_value
);
350 ASN_NULL_template::ASN_NULL_template()
355 ASN_NULL_template::ASN_NULL_template(template_sel other_value
)
356 : Base_Template(other_value
)
358 check_single_selection(other_value
);
361 ASN_NULL_template::ASN_NULL_template(asn_null_type
)
362 : Base_Template(SPECIFIC_VALUE
)
367 ASN_NULL_template::ASN_NULL_template(const ASN_NULL
& other_value
)
368 : Base_Template(SPECIFIC_VALUE
)
370 if (!other_value
.is_bound())
371 TTCN_error("Creating a template from an unbound ASN.1 NULL value.");
374 ASN_NULL_template::ASN_NULL_template(const OPTIONAL
<ASN_NULL
>& other_value
)
376 switch (other_value
.get_selection()) {
377 case OPTIONAL_PRESENT
:
378 set_selection(SPECIFIC_VALUE
);
381 set_selection(OMIT_VALUE
);
384 TTCN_error("Creating a template of ASN.1 NULL type from an unbound "
389 ASN_NULL_template::ASN_NULL_template(const ASN_NULL_template
& other_value
)
392 copy_template(other_value
);
395 ASN_NULL_template::~ASN_NULL_template()
400 ASN_NULL_template
& ASN_NULL_template::operator=(template_sel other_value
)
402 check_single_selection(other_value
);
404 set_selection(other_value
);
408 ASN_NULL_template
& ASN_NULL_template::operator=(asn_null_type
)
411 set_selection(SPECIFIC_VALUE
);
415 ASN_NULL_template
& ASN_NULL_template::operator=(const ASN_NULL
& other_value
)
417 if (!other_value
.is_bound()) TTCN_error("Assignment of an unbound ASN.1 "
418 "NULL value to a template.");
420 set_selection(SPECIFIC_VALUE
);
424 ASN_NULL_template
& ASN_NULL_template::operator=
425 (const OPTIONAL
<ASN_NULL
>& other_value
)
428 switch (other_value
.get_selection()) {
429 case OPTIONAL_PRESENT
:
430 set_selection(SPECIFIC_VALUE
);
433 set_selection(OMIT_VALUE
);
436 TTCN_error("Assignment of an unbound optional field to a template of "
442 ASN_NULL_template
& ASN_NULL_template::operator=
443 (const ASN_NULL_template
& other_value
)
445 if (&other_value
!= this) {
447 copy_template(other_value
);
452 boolean
ASN_NULL_template::match(asn_null_type other_value
,
453 boolean
/* legacy */) const
455 switch (template_selection
) {
463 case COMPLEMENTED_LIST
:
464 for (unsigned int i
= 0; i
< value_list
.n_values
; i
++)
465 if (value_list
.list_value
[i
].match(other_value
))
466 return template_selection
== VALUE_LIST
;
467 return template_selection
== COMPLEMENTED_LIST
;
469 TTCN_error("Matching with an uninitialized/unsupported template of "
475 boolean
ASN_NULL_template::match(const ASN_NULL
& other_value
,
476 boolean
/* legacy */) const
478 if (!other_value
.is_bound()) return FALSE
;
479 return match(ASN_NULL_VALUE
);
482 asn_null_type
ASN_NULL_template::valueof() const
484 if (template_selection
!= SPECIFIC_VALUE
|| is_ifpresent
)
485 TTCN_error("Performing a valueof "
486 "or send operation on a non-specific template of ASN.1 NULL type.");
487 return ASN_NULL_VALUE
;
490 void ASN_NULL_template::set_type(template_sel template_type
,
491 unsigned int list_length
)
493 if (template_type
!= VALUE_LIST
&& template_type
!= COMPLEMENTED_LIST
)
494 TTCN_error("Setting an invalid list type for a template of ASN.1 NULL "
497 set_selection(template_type
);
498 value_list
.n_values
= list_length
;
499 value_list
.list_value
= new ASN_NULL_template
[list_length
];
502 ASN_NULL_template
& ASN_NULL_template::list_item(unsigned int list_index
)
504 if (template_selection
!= VALUE_LIST
&&
505 template_selection
!= COMPLEMENTED_LIST
) TTCN_error("Accessing a list "
506 "element of a non-list template for ASN.1 NULL type.");
507 if (list_index
>= value_list
.n_values
)
508 TTCN_error("Index overflow in a value list template of ASN.1 NULL type.");
509 return value_list
.list_value
[list_index
];
512 void ASN_NULL_template::log() const
514 switch (template_selection
) {
516 TTCN_Logger::log_event_str("NULL");
518 case COMPLEMENTED_LIST
:
519 TTCN_Logger::log_event_str("complement ");
521 TTCN_Logger::log_char('(');
522 for (unsigned int i
= 0; i
< value_list
.n_values
; i
++) {
523 if (i
> 0) TTCN_Logger::log_event_str(", ");
524 value_list
.list_value
[i
].log();
526 TTCN_Logger::log_char(')');
534 void ASN_NULL_template::log_match(const ASN_NULL
& match_value
,
535 boolean
/* legacy */) const
537 if(TTCN_Logger::VERBOSITY_COMPACT
== TTCN_Logger::get_matching_verbosity()){
538 TTCN_Logger::print_logmatch_buffer();
539 TTCN_Logger::log_event_str(" := ");
542 TTCN_Logger::log_event_str(" with ");
544 if (match(match_value
)) TTCN_Logger::log_event_str(" matched");
545 else TTCN_Logger::log_event_str(" unmatched");
548 void ASN_NULL_template::set_param(Module_Param
& param
) {
549 param
.basic_check(Module_Param::BC_TEMPLATE
, "NULL template");
550 Module_Param_Ptr mp
= ¶m
;
551 if (param
.get_type() == Module_Param::MP_Reference
) {
552 mp
= param
.get_referenced_param();
554 switch (mp
->get_type()) {
555 case Module_Param::MP_Omit
:
558 case Module_Param::MP_Any
:
561 case Module_Param::MP_AnyOrNone
:
564 case Module_Param::MP_List_Template
:
565 case Module_Param::MP_ComplementList_Template
: {
566 ASN_NULL_template temp
;
567 temp
.set_type(mp
->get_type() == Module_Param::MP_List_Template
?
568 VALUE_LIST
: COMPLEMENTED_LIST
, mp
->get_size());
569 for (size_t i
=0; i
<mp
->get_size(); i
++) {
570 temp
.list_item(i
).set_param(*mp
->get_elem(i
));
574 case Module_Param::MP_Asn_Null
:
575 *this = ASN_NULL_VALUE
;
578 param
.type_error("NULL template");
580 is_ifpresent
= param
.get_ifpresent() || mp
->get_ifpresent();
583 Module_Param
* ASN_NULL_template::get_param(Module_Param_Name
& param_name
) const
585 Module_Param
* mp
= NULL
;
586 switch (template_selection
) {
587 case UNINITIALIZED_TEMPLATE
:
588 mp
= new Module_Param_Unbound();
591 mp
= new Module_Param_Omit();
594 mp
= new Module_Param_Any();
597 mp
= new Module_Param_AnyOrNone();
600 mp
= new Module_Param_Asn_Null();
603 case COMPLEMENTED_LIST
: {
604 if (template_selection
== VALUE_LIST
) {
605 mp
= new Module_Param_List_Template();
608 mp
= new Module_Param_ComplementList_Template();
610 for (size_t i
= 0; i
< value_list
.n_values
; ++i
) {
611 mp
->add_elem(value_list
.list_value
[i
].get_param(param_name
));
623 void ASN_NULL_template::encode_text(Text_Buf
& text_buf
) const
625 encode_text_base(text_buf
);
626 switch (template_selection
) {
633 case COMPLEMENTED_LIST
:
634 text_buf
.push_int(value_list
.n_values
);
635 for (unsigned int i
= 0; i
< value_list
.n_values
; i
++)
636 value_list
.list_value
[i
].encode_text(text_buf
);
639 TTCN_error("Text encoder: Encoding an undefined/unsupported template "
640 "of ASN.1 NULL type.");
644 void ASN_NULL_template::decode_text(Text_Buf
& text_buf
)
647 decode_text_base(text_buf
);
648 switch (template_selection
) {
655 case COMPLEMENTED_LIST
:
656 value_list
.n_values
= text_buf
.pull_int().get_val();
657 value_list
.list_value
= new ASN_NULL_template
[value_list
.n_values
];
658 for (unsigned int i
= 0; i
< value_list
.n_values
; i
++)
659 value_list
.list_value
[i
].decode_text(text_buf
);
662 TTCN_error("Text decoder: An unknown/unsupported selection was received "
663 "in a template for ASN.1 NULL type.");
667 boolean
ASN_NULL_template::is_present(boolean legacy
/* = FALSE */) const
669 if (template_selection
==UNINITIALIZED_TEMPLATE
) return FALSE
;
670 return !match_omit(legacy
);
673 boolean
ASN_NULL_template::match_omit(boolean legacy
/* = FALSE */) const
675 if (is_ifpresent
) return TRUE
;
676 switch (template_selection
) {
681 case COMPLEMENTED_LIST
:
683 // legacy behavior: 'omit' can appear in the value/complement list
684 for (unsigned int i
=0; i
<value_list
.n_values
; i
++)
685 if (value_list
.list_value
[i
].match_omit())
686 return template_selection
==VALUE_LIST
;
687 return template_selection
==COMPLEMENTED_LIST
;
696 #ifndef TITAN_RUNTIME_2
697 void ASN_NULL_template::check_restriction(template_res t_res
, const char* t_name
,
698 boolean legacy
/* = FALSE */) const
700 if (template_selection
==UNINITIALIZED_TEMPLATE
) return;
701 switch ((t_name
&&(t_res
==TR_VALUE
))?TR_OMIT
:t_res
) {
703 if (!is_ifpresent
&& template_selection
==SPECIFIC_VALUE
) return;
706 if (!is_ifpresent
&& (template_selection
==OMIT_VALUE
||
707 template_selection
==SPECIFIC_VALUE
)) return;
710 if (!match_omit(legacy
)) return;
715 TTCN_error("Restriction `%s' on template of type %s violated.",
716 get_res_name(t_res
), t_name
? t_name
: "ASN.1 NULL");