Commit | Line | Data |
---|---|---|
d44e3c4f | 1 | /****************************************************************************** |
2 | * Copyright (c) 2000-2016 Ericsson Telecom AB | |
3 | * All rights reserved. This program and the accompanying materials | |
4 | * are made available under the terms of the Eclipse Public License v1.0 | |
5 | * which accompanies this distribution, and is available at | |
6 | * http://www.eclipse.org/legal/epl-v10.html | |
7 | * | |
8 | * Contributors: | |
9 | * Balasko, Jeno | |
10 | * Baranyi, Botond | |
11 | * Beres, Szabolcs | |
12 | * Delic, Adam | |
13 | * Forstner, Matyas | |
14 | * Kovacs, Ferenc | |
15 | * Raduly, Csaba | |
16 | * Szabados, Kristof | |
17 | * Szabo, Bence Janos | |
18 | * Szabo, Janos Zoltan – initial implementation | |
19 | * Szalai, Gabor | |
20 | * Tatarka, Gabor | |
21 | * | |
22 | ******************************************************************************/ | |
970ed795 EL |
23 | #include <stdarg.h> |
24 | ||
25 | #include "ASN_Null.hh" | |
26 | #include "Parameters.h" | |
27 | #include "Param_Types.hh" | |
28 | #include "Error.hh" | |
29 | #include "Logger.hh" | |
30 | #include "Encdec.hh" | |
31 | #include "BER.hh" | |
32 | ||
33 | #include "../common/dbgnew.hh" | |
34 | ||
35 | ASN_NULL::ASN_NULL() | |
36 | { | |
37 | bound_flag = FALSE; | |
38 | } | |
39 | ||
40 | ASN_NULL::ASN_NULL(asn_null_type) | |
41 | { | |
42 | bound_flag = TRUE; | |
43 | } | |
44 | ||
45 | ASN_NULL::ASN_NULL(const ASN_NULL& other_value) | |
46 | : Base_Type(other_value) | |
47 | { | |
48 | if (!other_value.bound_flag) | |
49 | TTCN_error("Copying an unbound ASN.1 NULL value."); | |
50 | bound_flag = TRUE; | |
51 | } | |
52 | ||
53 | ASN_NULL& ASN_NULL::operator=(asn_null_type) | |
54 | { | |
55 | bound_flag = TRUE; | |
56 | return *this; | |
57 | } | |
58 | ||
59 | ASN_NULL& ASN_NULL::operator=(const ASN_NULL& other_value) | |
60 | { | |
61 | if (!other_value.bound_flag) | |
62 | TTCN_error("Assignment of an unbound ASN.1 NULL value."); | |
63 | bound_flag = TRUE; | |
64 | return *this; | |
65 | } | |
66 | ||
67 | boolean ASN_NULL::operator==(asn_null_type) const | |
68 | { | |
69 | if (!bound_flag) TTCN_error("The left operand of comparison is an unbound " | |
70 | "ASN.1 NULL value."); | |
71 | return TRUE; | |
72 | } | |
73 | ||
74 | boolean ASN_NULL::operator==(const ASN_NULL& other_value) const | |
75 | { | |
76 | if (!bound_flag) TTCN_error("The left operand of comparison is an unbound " | |
77 | "ASN.1 NULL value."); | |
78 | if (!other_value.bound_flag) TTCN_error("The right operand of comparison " | |
79 | "is an unbound ASN.1 NULL value."); | |
80 | return TRUE; | |
81 | } | |
82 | ||
83 | void ASN_NULL::log() const | |
84 | { | |
85 | if (bound_flag) TTCN_Logger::log_event_str("NULL"); | |
86 | else TTCN_Logger::log_event_unbound(); | |
87 | } | |
88 | ||
89 | void ASN_NULL::set_param(Module_Param& param) { | |
90 | param.basic_check(Module_Param::BC_VALUE, "NULL value"); | |
3abe9331 | 91 | Module_Param_Ptr mp = ¶m; |
92 | if (param.get_type() == Module_Param::MP_Reference) { | |
93 | mp = param.get_referenced_param(); | |
94 | } | |
95 | if (mp->get_type()!=Module_Param::MP_Asn_Null) param.type_error("NULL value"); | |
970ed795 EL |
96 | bound_flag = TRUE; |
97 | } | |
98 | ||
3abe9331 | 99 | Module_Param* ASN_NULL::get_param(Module_Param_Name& /* param_name */) const |
100 | { | |
101 | if (!is_bound()) { | |
102 | return new Module_Param_Unbound(); | |
103 | } | |
104 | return new Module_Param_Asn_Null(); | |
105 | } | |
106 | ||
970ed795 EL |
107 | void ASN_NULL::encode_text(Text_Buf&) const |
108 | { | |
109 | if (!bound_flag) | |
110 | TTCN_error("Text encoder: Encoding an unbound ASN.1 NULL value."); | |
111 | } | |
112 | ||
113 | void ASN_NULL::decode_text(Text_Buf&) | |
114 | { | |
115 | bound_flag = TRUE; | |
116 | } | |
117 | ||
118 | void ASN_NULL::encode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf, | |
119 | TTCN_EncDec::coding_t p_coding, ...) const | |
120 | { | |
121 | va_list pvar; | |
122 | va_start(pvar, p_coding); | |
123 | switch(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); | |
131 | break;} | |
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); | |
af710487 | 135 | XER_encode(*p_td.xer, p_buf, XER_coding, 0, 0); |
136 | break;} | |
137 | case TTCN_EncDec::CT_JSON: { | |
138 | TTCN_EncDec_ErrorContext ec("While JSON-encoding type '%s': ", p_td.name); | |
139 | if(!p_td.json) | |
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()); | |
970ed795 EL |
145 | break;} |
146 | case TTCN_EncDec::CT_RAW: | |
147 | default: | |
148 | TTCN_error("Unknown coding method requested to encode type '%s'", | |
149 | p_td.name); | |
150 | } | |
151 | va_end(pvar); | |
152 | } | |
153 | ||
154 | void ASN_NULL::decode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf, | |
155 | TTCN_EncDec::coding_t p_coding, ...) | |
156 | { | |
157 | va_list pvar; | |
158 | va_start(pvar, p_coding); | |
159 | switch(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); | |
163 | ASN_BER_TLV_t tlv; | |
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()); | |
167 | break;} | |
168 | case TTCN_EncDec::CT_XER: { | |
af710487 | 169 | TTCN_EncDec_ErrorContext ec("While XER-decoding type '%s': ", p_td.name); |
970ed795 EL |
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) | |
176 | break; | |
177 | } | |
feade998 | 178 | XER_decode(*p_td.xer, reader, XER_coding, XER_NONE, 0); |
970ed795 EL |
179 | size_t bytes = reader.ByteConsumed(); |
180 | p_buf.set_pos(bytes); | |
181 | break;} | |
af710487 | 182 | case TTCN_EncDec::CT_JSON: { |
183 | TTCN_EncDec_ErrorContext ec("While JSON-decoding type '%s': ", p_td.name); | |
184 | if(!p_td.json) | |
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" | |
192 | , p_td.name); | |
193 | p_buf.set_pos(tok.get_buf_pos()); | |
194 | break;} | |
970ed795 EL |
195 | case TTCN_EncDec::CT_RAW: |
196 | default: | |
197 | TTCN_error("Unknown coding method requested to decode type '%s'", | |
198 | p_td.name); | |
199 | } | |
200 | va_end(pvar); | |
201 | } | |
202 | ||
203 | ASN_BER_TLV_t* | |
204 | ASN_NULL::BER_encode_TLV(const TTCN_Typedescriptor_t& p_td, | |
205 | unsigned p_coding) const | |
206 | { | |
207 | BER_chk_descr(p_td); | |
208 | ASN_BER_TLV_t *new_tlv=BER_encode_chk_bound(is_bound()); | |
209 | if(!new_tlv) { | |
210 | new_tlv=ASN_BER_TLV_t::construct(0, NULL); | |
211 | } | |
212 | new_tlv=ASN_BER_V2TLV(new_tlv, p_td, p_coding); | |
213 | return new_tlv; | |
214 | } | |
215 | ||
216 | boolean ASN_NULL::BER_decode_TLV(const TTCN_Typedescriptor_t& p_td, | |
217 | const ASN_BER_TLV_t& p_tlv, | |
218 | unsigned L_form) | |
219 | { | |
220 | bound_flag = FALSE; | |
221 | BER_chk_descr(p_td); | |
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."); | |
228 | bound_flag=TRUE; | |
229 | return TRUE; | |
230 | } | |
231 | ||
232 | int ASN_NULL::XER_encode(const XERdescriptor_t& p_td, | |
af710487 | 233 | TTCN_Buffer& p_buf, unsigned int flavor, int indent, embed_values_enc_struct_t*) const |
970ed795 EL |
234 | { |
235 | int exer = is_exer(flavor); | |
236 | TTCN_EncDec_ErrorContext ec("While XER encoding NULL type: "); | |
237 | if(!is_bound()) { | |
238 | TTCN_EncDec_ErrorContext::error | |
239 | (TTCN_EncDec::ET_UNBOUND, "Encoding an unbound ASN.1 NULL value."); | |
240 | } | |
241 | ||
242 | int indenting = !is_canonical(flavor) && !is_record_of(flavor); | |
243 | int encoded_length=(int)p_buf.get_len(); | |
244 | ||
245 | if (indenting) do_indent(p_buf, indent); | |
246 | p_buf.put_c('<'); | |
247 | ||
248 | // empty element tag | |
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]); | |
251 | ||
252 | p_buf.put_s(2 + indenting , (const unsigned char*)"/>\n"); | |
253 | return (int)p_buf.get_len() - encoded_length; | |
254 | } | |
255 | ||
256 | int ASN_NULL::XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& reader, | |
feade998 | 257 | unsigned int flavor, unsigned int /*flavor2*/, embed_values_dec_struct_t*) |
970ed795 EL |
258 | { |
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(); | |
267 | break; | |
268 | } | |
269 | } | |
270 | bound_flag = TRUE; | |
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() ?? | |
278 | break; | |
279 | } | |
280 | } // next | |
281 | } // if gol | |
282 | ||
283 | reader.Read(); | |
284 | return 1; // decode successful | |
285 | } | |
286 | ||
af710487 | 287 | int ASN_NULL::JSON_encode(const TTCN_Typedescriptor_t&, JSON_Tokenizer& p_tok) const |
288 | { | |
289 | if (!is_bound()) { | |
290 | TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND, | |
291 | "Encoding an unbound ASN.1 NULL value."); | |
292 | return -1; | |
293 | } | |
294 | ||
295 | return p_tok.put_next_token(JSON_TOKEN_LITERAL_NULL); | |
296 | } | |
297 | ||
298 | int ASN_NULL::JSON_decode(const TTCN_Typedescriptor_t&, JSON_Tokenizer& p_tok, boolean p_silent) | |
299 | { | |
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; | |
305 | } | |
306 | else if (JSON_TOKEN_LITERAL_NULL != token) { | |
307 | return JSON_ERROR_INVALID_TOKEN; | |
308 | } | |
309 | bound_flag = TRUE; | |
310 | return dec_len; | |
311 | } | |
312 | ||
970ed795 EL |
313 | boolean operator==(asn_null_type, const ASN_NULL& other_value) |
314 | { | |
315 | if (!other_value.is_bound()) TTCN_error("The right operand of comparison " | |
316 | "is an unbound ASN.1 NULL value."); | |
317 | return TRUE; | |
318 | } | |
319 | ||
320 | void ASN_NULL_template::clean_up() | |
321 | { | |
322 | if (template_selection == VALUE_LIST || | |
323 | template_selection == COMPLEMENTED_LIST) delete [] value_list.list_value; | |
324 | template_selection = UNINITIALIZED_TEMPLATE; | |
325 | } | |
326 | ||
327 | void ASN_NULL_template::copy_template(const ASN_NULL_template& other_value) | |
328 | { | |
329 | switch (other_value.template_selection) { | |
330 | case SPECIFIC_VALUE: | |
331 | case OMIT_VALUE: | |
332 | case ANY_VALUE: | |
333 | case ANY_OR_OMIT: | |
334 | break; | |
335 | case VALUE_LIST: | |
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]); | |
342 | break; | |
343 | default: | |
344 | TTCN_error("Copying an uninitialized/unsupported template of ASN.1 " | |
345 | "NULL type."); | |
346 | } | |
347 | set_selection(other_value); | |
348 | } | |
349 | ||
350 | ASN_NULL_template::ASN_NULL_template() | |
351 | { | |
352 | ||
353 | } | |
354 | ||
355 | ASN_NULL_template::ASN_NULL_template(template_sel other_value) | |
356 | : Base_Template(other_value) | |
357 | { | |
358 | check_single_selection(other_value); | |
359 | } | |
360 | ||
361 | ASN_NULL_template::ASN_NULL_template(asn_null_type) | |
362 | : Base_Template(SPECIFIC_VALUE) | |
363 | { | |
364 | ||
365 | } | |
366 | ||
367 | ASN_NULL_template::ASN_NULL_template(const ASN_NULL& other_value) | |
368 | : Base_Template(SPECIFIC_VALUE) | |
369 | { | |
370 | if (!other_value.is_bound()) | |
371 | TTCN_error("Creating a template from an unbound ASN.1 NULL value."); | |
372 | } | |
373 | ||
374 | ASN_NULL_template::ASN_NULL_template(const OPTIONAL<ASN_NULL>& other_value) | |
375 | { | |
376 | switch (other_value.get_selection()) { | |
377 | case OPTIONAL_PRESENT: | |
378 | set_selection(SPECIFIC_VALUE); | |
379 | break; | |
380 | case OPTIONAL_OMIT: | |
381 | set_selection(OMIT_VALUE); | |
382 | break; | |
383 | default: | |
384 | TTCN_error("Creating a template of ASN.1 NULL type from an unbound " | |
385 | "optional field."); | |
386 | } | |
387 | } | |
388 | ||
389 | ASN_NULL_template::ASN_NULL_template(const ASN_NULL_template& other_value) | |
390 | : Base_Template() | |
391 | { | |
392 | copy_template(other_value); | |
393 | } | |
394 | ||
395 | ASN_NULL_template::~ASN_NULL_template() | |
396 | { | |
397 | clean_up(); | |
398 | } | |
399 | ||
400 | ASN_NULL_template& ASN_NULL_template::operator=(template_sel other_value) | |
401 | { | |
402 | check_single_selection(other_value); | |
403 | clean_up(); | |
404 | set_selection(other_value); | |
405 | return *this; | |
406 | } | |
407 | ||
408 | ASN_NULL_template& ASN_NULL_template::operator=(asn_null_type) | |
409 | { | |
410 | clean_up(); | |
411 | set_selection(SPECIFIC_VALUE); | |
412 | return *this; | |
413 | } | |
414 | ||
415 | ASN_NULL_template& ASN_NULL_template::operator=(const ASN_NULL& other_value) | |
416 | { | |
417 | if (!other_value.is_bound()) TTCN_error("Assignment of an unbound ASN.1 " | |
418 | "NULL value to a template."); | |
419 | clean_up(); | |
420 | set_selection(SPECIFIC_VALUE); | |
421 | return *this; | |
422 | } | |
423 | ||
424 | ASN_NULL_template& ASN_NULL_template::operator= | |
425 | (const OPTIONAL<ASN_NULL>& other_value) | |
426 | { | |
427 | clean_up(); | |
428 | switch (other_value.get_selection()) { | |
429 | case OPTIONAL_PRESENT: | |
430 | set_selection(SPECIFIC_VALUE); | |
431 | break; | |
432 | case OPTIONAL_OMIT: | |
433 | set_selection(OMIT_VALUE); | |
434 | break; | |
435 | default: | |
436 | TTCN_error("Assignment of an unbound optional field to a template of " | |
437 | "ASN.1 NULL type."); | |
438 | } | |
439 | return *this; | |
440 | } | |
441 | ||
442 | ASN_NULL_template& ASN_NULL_template::operator= | |
443 | (const ASN_NULL_template& other_value) | |
444 | { | |
445 | if (&other_value != this) { | |
446 | clean_up(); | |
447 | copy_template(other_value); | |
448 | } | |
449 | return *this; | |
450 | } | |
451 | ||
3abe9331 | 452 | boolean ASN_NULL_template::match(asn_null_type other_value, |
453 | boolean /* legacy */) const | |
970ed795 EL |
454 | { |
455 | switch (template_selection) { | |
456 | case OMIT_VALUE: | |
457 | return FALSE; | |
458 | case SPECIFIC_VALUE: | |
459 | case ANY_VALUE: | |
460 | case ANY_OR_OMIT: | |
461 | return TRUE; | |
462 | case VALUE_LIST: | |
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; | |
468 | default: | |
469 | TTCN_error("Matching with an uninitialized/unsupported template of " | |
470 | "ASN.1 NULL type."); | |
471 | } | |
472 | return FALSE; | |
473 | } | |
474 | ||
3abe9331 | 475 | boolean ASN_NULL_template::match(const ASN_NULL& other_value, |
476 | boolean /* legacy */) const | |
970ed795 EL |
477 | { |
478 | if (!other_value.is_bound()) return FALSE; | |
479 | return match(ASN_NULL_VALUE); | |
480 | } | |
481 | ||
482 | asn_null_type ASN_NULL_template::valueof() const | |
483 | { | |
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; | |
488 | } | |
489 | ||
490 | void ASN_NULL_template::set_type(template_sel template_type, | |
491 | unsigned int list_length) | |
492 | { | |
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 " | |
495 | "type."); | |
496 | clean_up(); | |
497 | set_selection(template_type); | |
498 | value_list.n_values = list_length; | |
499 | value_list.list_value = new ASN_NULL_template[list_length]; | |
500 | } | |
501 | ||
502 | ASN_NULL_template& ASN_NULL_template::list_item(unsigned int list_index) | |
503 | { | |
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]; | |
510 | } | |
511 | ||
512 | void ASN_NULL_template::log() const | |
513 | { | |
514 | switch (template_selection) { | |
515 | case SPECIFIC_VALUE: | |
516 | TTCN_Logger::log_event_str("NULL"); | |
517 | break; | |
518 | case COMPLEMENTED_LIST: | |
519 | TTCN_Logger::log_event_str("complement "); | |
520 | case VALUE_LIST: | |
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(); | |
525 | } | |
526 | TTCN_Logger::log_char(')'); | |
527 | break; | |
528 | default: | |
529 | log_generic(); | |
530 | } | |
531 | log_ifpresent(); | |
532 | } | |
533 | ||
3abe9331 | 534 | void ASN_NULL_template::log_match(const ASN_NULL& match_value, |
535 | boolean /* legacy */) const | |
970ed795 EL |
536 | { |
537 | if(TTCN_Logger::VERBOSITY_COMPACT == TTCN_Logger::get_matching_verbosity()){ | |
538 | TTCN_Logger::print_logmatch_buffer(); | |
539 | TTCN_Logger::log_event_str(" := "); | |
540 | } | |
541 | match_value.log(); | |
542 | TTCN_Logger::log_event_str(" with "); | |
543 | log(); | |
544 | if (match(match_value)) TTCN_Logger::log_event_str(" matched"); | |
545 | else TTCN_Logger::log_event_str(" unmatched"); | |
546 | } | |
547 | ||
548 | void ASN_NULL_template::set_param(Module_Param& param) { | |
549 | param.basic_check(Module_Param::BC_TEMPLATE, "NULL template"); | |
3abe9331 | 550 | Module_Param_Ptr mp = ¶m; |
551 | if (param.get_type() == Module_Param::MP_Reference) { | |
552 | mp = param.get_referenced_param(); | |
553 | } | |
554 | switch (mp->get_type()) { | |
970ed795 EL |
555 | case Module_Param::MP_Omit: |
556 | *this = OMIT_VALUE; | |
557 | break; | |
558 | case Module_Param::MP_Any: | |
559 | *this = ANY_VALUE; | |
560 | break; | |
561 | case Module_Param::MP_AnyOrNone: | |
562 | *this = ANY_OR_OMIT; | |
563 | break; | |
564 | case Module_Param::MP_List_Template: | |
3abe9331 | 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)); | |
970ed795 | 571 | } |
3abe9331 | 572 | *this = temp; |
573 | break; } | |
970ed795 EL |
574 | case Module_Param::MP_Asn_Null: |
575 | *this = ASN_NULL_VALUE; | |
576 | break; | |
577 | default: | |
578 | param.type_error("NULL template"); | |
579 | } | |
3abe9331 | 580 | is_ifpresent = param.get_ifpresent() || mp->get_ifpresent(); |
581 | } | |
582 | ||
583 | Module_Param* ASN_NULL_template::get_param(Module_Param_Name& param_name) const | |
584 | { | |
585 | Module_Param* mp = NULL; | |
586 | switch (template_selection) { | |
587 | case UNINITIALIZED_TEMPLATE: | |
588 | mp = new Module_Param_Unbound(); | |
589 | break; | |
590 | case OMIT_VALUE: | |
591 | mp = new Module_Param_Omit(); | |
592 | break; | |
593 | case ANY_VALUE: | |
594 | mp = new Module_Param_Any(); | |
595 | break; | |
596 | case ANY_OR_OMIT: | |
597 | mp = new Module_Param_AnyOrNone(); | |
598 | break; | |
599 | case SPECIFIC_VALUE: | |
600 | mp = new Module_Param_Asn_Null(); | |
601 | break; | |
602 | case VALUE_LIST: | |
603 | case COMPLEMENTED_LIST: { | |
604 | if (template_selection == VALUE_LIST) { | |
605 | mp = new Module_Param_List_Template(); | |
606 | } | |
607 | else { | |
608 | mp = new Module_Param_ComplementList_Template(); | |
609 | } | |
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)); | |
612 | } | |
613 | break; } | |
614 | default: | |
615 | break; | |
616 | } | |
617 | if (is_ifpresent) { | |
618 | mp->set_ifpresent(); | |
619 | } | |
620 | return mp; | |
970ed795 EL |
621 | } |
622 | ||
623 | void ASN_NULL_template::encode_text(Text_Buf& text_buf) const | |
624 | { | |
625 | encode_text_base(text_buf); | |
626 | switch (template_selection) { | |
627 | case SPECIFIC_VALUE: | |
628 | case OMIT_VALUE: | |
629 | case ANY_VALUE: | |
630 | case ANY_OR_OMIT: | |
631 | break; | |
632 | case VALUE_LIST: | |
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); | |
637 | break; | |
638 | default: | |
639 | TTCN_error("Text encoder: Encoding an undefined/unsupported template " | |
640 | "of ASN.1 NULL type."); | |
641 | } | |
642 | } | |
643 | ||
644 | void ASN_NULL_template::decode_text(Text_Buf& text_buf) | |
645 | { | |
646 | clean_up(); | |
647 | decode_text_base(text_buf); | |
648 | switch (template_selection) { | |
649 | case SPECIFIC_VALUE: | |
650 | case OMIT_VALUE: | |
651 | case ANY_VALUE: | |
652 | case ANY_OR_OMIT: | |
653 | break; | |
654 | case VALUE_LIST: | |
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); | |
660 | break; | |
661 | default: | |
662 | TTCN_error("Text decoder: An unknown/unsupported selection was received " | |
663 | "in a template for ASN.1 NULL type."); | |
664 | } | |
665 | } | |
666 | ||
3abe9331 | 667 | boolean ASN_NULL_template::is_present(boolean legacy /* = FALSE */) const |
970ed795 EL |
668 | { |
669 | if (template_selection==UNINITIALIZED_TEMPLATE) return FALSE; | |
3abe9331 | 670 | return !match_omit(legacy); |
970ed795 EL |
671 | } |
672 | ||
3abe9331 | 673 | boolean ASN_NULL_template::match_omit(boolean legacy /* = FALSE */) const |
970ed795 EL |
674 | { |
675 | if (is_ifpresent) return TRUE; | |
676 | switch (template_selection) { | |
677 | case OMIT_VALUE: | |
678 | case ANY_OR_OMIT: | |
679 | return TRUE; | |
680 | case VALUE_LIST: | |
681 | case COMPLEMENTED_LIST: | |
3abe9331 | 682 | if (legacy) { |
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; | |
688 | } | |
689 | // else fall through | |
970ed795 EL |
690 | default: |
691 | return FALSE; | |
692 | } | |
693 | return FALSE; | |
694 | } | |
695 | ||
696 | #ifndef TITAN_RUNTIME_2 | |
3abe9331 | 697 | void ASN_NULL_template::check_restriction(template_res t_res, const char* t_name, |
698 | boolean legacy /* = FALSE */) const | |
970ed795 EL |
699 | { |
700 | if (template_selection==UNINITIALIZED_TEMPLATE) return; | |
701 | switch ((t_name&&(t_res==TR_VALUE))?TR_OMIT:t_res) { | |
702 | case TR_VALUE: | |
703 | if (!is_ifpresent && template_selection==SPECIFIC_VALUE) return; | |
704 | break; | |
705 | case TR_OMIT: | |
706 | if (!is_ifpresent && (template_selection==OMIT_VALUE || | |
707 | template_selection==SPECIFIC_VALUE)) return; | |
708 | break; | |
709 | case TR_PRESENT: | |
3abe9331 | 710 | if (!match_omit(legacy)) return; |
970ed795 EL |
711 | break; |
712 | default: | |
713 | return; | |
714 | } | |
715 | TTCN_error("Restriction `%s' on template of type %s violated.", | |
716 | get_res_name(t_res), t_name ? t_name : "ASN.1 NULL"); | |
717 | } | |
718 | #endif |