Commit | Line | Data |
---|---|---|
970ed795 EL |
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 | /////////////////////////////////////////////////////////////////////////////// | |
8 | #include <stdarg.h> | |
9 | ||
10 | #include "ASN_Null.hh" | |
11 | #include "Parameters.h" | |
12 | #include "Param_Types.hh" | |
13 | #include "Error.hh" | |
14 | #include "Logger.hh" | |
15 | #include "Encdec.hh" | |
16 | #include "BER.hh" | |
17 | ||
18 | #include "../common/dbgnew.hh" | |
19 | ||
20 | ASN_NULL::ASN_NULL() | |
21 | { | |
22 | bound_flag = FALSE; | |
23 | } | |
24 | ||
25 | ASN_NULL::ASN_NULL(asn_null_type) | |
26 | { | |
27 | bound_flag = TRUE; | |
28 | } | |
29 | ||
30 | ASN_NULL::ASN_NULL(const ASN_NULL& other_value) | |
31 | : Base_Type(other_value) | |
32 | { | |
33 | if (!other_value.bound_flag) | |
34 | TTCN_error("Copying an unbound ASN.1 NULL value."); | |
35 | bound_flag = TRUE; | |
36 | } | |
37 | ||
38 | ASN_NULL& ASN_NULL::operator=(asn_null_type) | |
39 | { | |
40 | bound_flag = TRUE; | |
41 | return *this; | |
42 | } | |
43 | ||
44 | ASN_NULL& ASN_NULL::operator=(const ASN_NULL& other_value) | |
45 | { | |
46 | if (!other_value.bound_flag) | |
47 | TTCN_error("Assignment of an unbound ASN.1 NULL value."); | |
48 | bound_flag = TRUE; | |
49 | return *this; | |
50 | } | |
51 | ||
52 | boolean ASN_NULL::operator==(asn_null_type) const | |
53 | { | |
54 | if (!bound_flag) TTCN_error("The left operand of comparison is an unbound " | |
55 | "ASN.1 NULL value."); | |
56 | return TRUE; | |
57 | } | |
58 | ||
59 | boolean ASN_NULL::operator==(const ASN_NULL& other_value) const | |
60 | { | |
61 | if (!bound_flag) TTCN_error("The left operand of comparison is an unbound " | |
62 | "ASN.1 NULL value."); | |
63 | if (!other_value.bound_flag) TTCN_error("The right operand of comparison " | |
64 | "is an unbound ASN.1 NULL value."); | |
65 | return TRUE; | |
66 | } | |
67 | ||
68 | void ASN_NULL::log() const | |
69 | { | |
70 | if (bound_flag) TTCN_Logger::log_event_str("NULL"); | |
71 | else TTCN_Logger::log_event_unbound(); | |
72 | } | |
73 | ||
74 | void ASN_NULL::set_param(Module_Param& param) { | |
75 | param.basic_check(Module_Param::BC_VALUE, "NULL value"); | |
76 | if (param.get_type()!=Module_Param::MP_Asn_Null) param.type_error("NULL value"); | |
77 | bound_flag = TRUE; | |
78 | } | |
79 | ||
80 | void ASN_NULL::encode_text(Text_Buf&) const | |
81 | { | |
82 | if (!bound_flag) | |
83 | TTCN_error("Text encoder: Encoding an unbound ASN.1 NULL value."); | |
84 | } | |
85 | ||
86 | void ASN_NULL::decode_text(Text_Buf&) | |
87 | { | |
88 | bound_flag = TRUE; | |
89 | } | |
90 | ||
91 | void ASN_NULL::encode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf, | |
92 | TTCN_EncDec::coding_t p_coding, ...) const | |
93 | { | |
94 | va_list pvar; | |
95 | va_start(pvar, p_coding); | |
96 | switch(p_coding) { | |
97 | case TTCN_EncDec::CT_BER: { | |
98 | TTCN_EncDec_ErrorContext ec("While BER-encoding type '%s': ", p_td.name); | |
99 | unsigned BER_coding=va_arg(pvar, unsigned); | |
100 | BER_encode_chk_coding(BER_coding); | |
101 | ASN_BER_TLV_t *tlv=BER_encode_TLV(p_td, BER_coding); | |
102 | tlv->put_in_buffer(p_buf); | |
103 | ASN_BER_TLV_t::destruct(tlv); | |
104 | break;} | |
105 | case TTCN_EncDec::CT_XER: { | |
106 | TTCN_EncDec_ErrorContext ec("While XER-encoding type '%s': ", p_td.name); | |
107 | unsigned XER_coding=va_arg(pvar, unsigned); | |
af710487 | 108 | XER_encode(*p_td.xer, p_buf, XER_coding, 0, 0); |
109 | break;} | |
110 | case TTCN_EncDec::CT_JSON: { | |
111 | TTCN_EncDec_ErrorContext ec("While JSON-encoding type '%s': ", p_td.name); | |
112 | if(!p_td.json) | |
113 | TTCN_EncDec_ErrorContext::error_internal | |
114 | ("No JSON descriptor available for type '%s'.", p_td.name); | |
115 | JSON_Tokenizer tok(va_arg(pvar, int) != 0); | |
116 | JSON_encode(p_td, tok); | |
117 | p_buf.put_s(tok.get_buffer_length(), (const unsigned char*)tok.get_buffer()); | |
970ed795 EL |
118 | break;} |
119 | case TTCN_EncDec::CT_RAW: | |
120 | default: | |
121 | TTCN_error("Unknown coding method requested to encode type '%s'", | |
122 | p_td.name); | |
123 | } | |
124 | va_end(pvar); | |
125 | } | |
126 | ||
127 | void ASN_NULL::decode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf, | |
128 | TTCN_EncDec::coding_t p_coding, ...) | |
129 | { | |
130 | va_list pvar; | |
131 | va_start(pvar, p_coding); | |
132 | switch(p_coding) { | |
133 | case TTCN_EncDec::CT_BER: { | |
134 | TTCN_EncDec_ErrorContext ec("While BER-decoding type '%s': ", p_td.name); | |
135 | unsigned L_form=va_arg(pvar, unsigned); | |
136 | ASN_BER_TLV_t tlv; | |
137 | BER_decode_str2TLV(p_buf, tlv, L_form); | |
138 | BER_decode_TLV(p_td, tlv, L_form); | |
139 | if(tlv.isComplete) p_buf.increase_pos(tlv.get_len()); | |
140 | break;} | |
141 | case TTCN_EncDec::CT_XER: { | |
af710487 | 142 | TTCN_EncDec_ErrorContext ec("While XER-decoding type '%s': ", p_td.name); |
970ed795 EL |
143 | unsigned XER_coding=va_arg(pvar, unsigned); |
144 | XmlReaderWrap reader(p_buf); | |
145 | int success = reader.Read(); | |
146 | for (; success==1; success=reader.Read()) { | |
147 | int type = reader.NodeType(); | |
148 | if (type==XML_READER_TYPE_ELEMENT) | |
149 | break; | |
150 | } | |
af710487 | 151 | XER_decode(*p_td.xer, reader, XER_coding, 0); |
970ed795 EL |
152 | size_t bytes = reader.ByteConsumed(); |
153 | p_buf.set_pos(bytes); | |
154 | break;} | |
af710487 | 155 | case TTCN_EncDec::CT_JSON: { |
156 | TTCN_EncDec_ErrorContext ec("While JSON-decoding type '%s': ", p_td.name); | |
157 | if(!p_td.json) | |
158 | TTCN_EncDec_ErrorContext::error_internal | |
159 | ("No JSON descriptor available for type '%s'.", p_td.name); | |
160 | JSON_Tokenizer tok((const char*)p_buf.get_data(), p_buf.get_len()); | |
161 | if(JSON_decode(p_td, tok, false)<0) | |
162 | ec.error(TTCN_EncDec::ET_INCOMPL_MSG, | |
163 | "Can not decode type '%s', because invalid or incomplete" | |
164 | " message was received" | |
165 | , p_td.name); | |
166 | p_buf.set_pos(tok.get_buf_pos()); | |
167 | break;} | |
970ed795 EL |
168 | case TTCN_EncDec::CT_RAW: |
169 | default: | |
170 | TTCN_error("Unknown coding method requested to decode type '%s'", | |
171 | p_td.name); | |
172 | } | |
173 | va_end(pvar); | |
174 | } | |
175 | ||
176 | ASN_BER_TLV_t* | |
177 | ASN_NULL::BER_encode_TLV(const TTCN_Typedescriptor_t& p_td, | |
178 | unsigned p_coding) const | |
179 | { | |
180 | BER_chk_descr(p_td); | |
181 | ASN_BER_TLV_t *new_tlv=BER_encode_chk_bound(is_bound()); | |
182 | if(!new_tlv) { | |
183 | new_tlv=ASN_BER_TLV_t::construct(0, NULL); | |
184 | } | |
185 | new_tlv=ASN_BER_V2TLV(new_tlv, p_td, p_coding); | |
186 | return new_tlv; | |
187 | } | |
188 | ||
189 | boolean ASN_NULL::BER_decode_TLV(const TTCN_Typedescriptor_t& p_td, | |
190 | const ASN_BER_TLV_t& p_tlv, | |
191 | unsigned L_form) | |
192 | { | |
193 | bound_flag = FALSE; | |
194 | BER_chk_descr(p_td); | |
195 | ASN_BER_TLV_t stripped_tlv; | |
196 | BER_decode_strip_tags(*p_td.ber, p_tlv, L_form, stripped_tlv); | |
197 | TTCN_EncDec_ErrorContext ec("While decoding NULL type: "); | |
198 | stripped_tlv.chk_constructed_flag(FALSE); | |
199 | if(!stripped_tlv.V_tlvs_selected && stripped_tlv.V.str.Vlen!=0) | |
200 | ec.error(TTCN_EncDec::ET_INVAL_MSG, "Length of V-part is not 0."); | |
201 | bound_flag=TRUE; | |
202 | return TRUE; | |
203 | } | |
204 | ||
205 | int ASN_NULL::XER_encode(const XERdescriptor_t& p_td, | |
af710487 | 206 | TTCN_Buffer& p_buf, unsigned int flavor, int indent, embed_values_enc_struct_t*) const |
970ed795 EL |
207 | { |
208 | int exer = is_exer(flavor); | |
209 | TTCN_EncDec_ErrorContext ec("While XER encoding NULL type: "); | |
210 | if(!is_bound()) { | |
211 | TTCN_EncDec_ErrorContext::error | |
212 | (TTCN_EncDec::ET_UNBOUND, "Encoding an unbound ASN.1 NULL value."); | |
213 | } | |
214 | ||
215 | int indenting = !is_canonical(flavor) && !is_record_of(flavor); | |
216 | int encoded_length=(int)p_buf.get_len(); | |
217 | ||
218 | if (indenting) do_indent(p_buf, indent); | |
219 | p_buf.put_c('<'); | |
220 | ||
221 | // empty element tag | |
222 | if (exer) write_ns_prefix(p_td, p_buf); | |
223 | p_buf.put_s((size_t)p_td.namelens[exer]-2, (const unsigned char*)p_td.names[exer]); | |
224 | ||
225 | p_buf.put_s(2 + indenting , (const unsigned char*)"/>\n"); | |
226 | return (int)p_buf.get_len() - encoded_length; | |
227 | } | |
228 | ||
229 | int ASN_NULL::XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& reader, | |
af710487 | 230 | unsigned int flavor, embed_values_dec_struct_t*) |
970ed795 EL |
231 | { |
232 | int exer = is_exer(flavor); | |
233 | TTCN_EncDec_ErrorContext ec("While XER decoding NULL type: "); | |
234 | int success = reader.Ok(), depth = -1; | |
235 | for (; success == 1; success = reader.Read()) { | |
236 | int type = reader.NodeType(); | |
237 | if (XML_READER_TYPE_ELEMENT == type) { | |
238 | verify_name(reader, p_td, exer); | |
239 | depth = reader.Depth(); | |
240 | break; | |
241 | } | |
242 | } | |
243 | bound_flag = TRUE; | |
244 | int gol = reader.IsEmptyElement(); | |
245 | if (!gol) { // shouldn't happen | |
246 | for (success = reader.Read(); success == 1; success = reader.Read()) { | |
247 | int type = reader.NodeType(); | |
248 | if (XML_READER_TYPE_END_ELEMENT == type) { | |
249 | verify_end(reader, p_td, depth, exer); | |
250 | // FIXME reader.Read() ?? | |
251 | break; | |
252 | } | |
253 | } // next | |
254 | } // if gol | |
255 | ||
256 | reader.Read(); | |
257 | return 1; // decode successful | |
258 | } | |
259 | ||
af710487 | 260 | int ASN_NULL::JSON_encode(const TTCN_Typedescriptor_t&, JSON_Tokenizer& p_tok) const |
261 | { | |
262 | if (!is_bound()) { | |
263 | TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND, | |
264 | "Encoding an unbound ASN.1 NULL value."); | |
265 | return -1; | |
266 | } | |
267 | ||
268 | return p_tok.put_next_token(JSON_TOKEN_LITERAL_NULL); | |
269 | } | |
270 | ||
271 | int ASN_NULL::JSON_decode(const TTCN_Typedescriptor_t&, JSON_Tokenizer& p_tok, boolean p_silent) | |
272 | { | |
273 | json_token_t token = JSON_TOKEN_NONE; | |
274 | int dec_len = p_tok.get_next_token(&token, NULL, NULL); | |
275 | if (JSON_TOKEN_ERROR == token) { | |
276 | JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_BAD_TOKEN_ERROR, ""); | |
277 | return JSON_ERROR_FATAL; | |
278 | } | |
279 | else if (JSON_TOKEN_LITERAL_NULL != token) { | |
280 | return JSON_ERROR_INVALID_TOKEN; | |
281 | } | |
282 | bound_flag = TRUE; | |
283 | return dec_len; | |
284 | } | |
285 | ||
970ed795 EL |
286 | boolean operator==(asn_null_type, const ASN_NULL& other_value) |
287 | { | |
288 | if (!other_value.is_bound()) TTCN_error("The right operand of comparison " | |
289 | "is an unbound ASN.1 NULL value."); | |
290 | return TRUE; | |
291 | } | |
292 | ||
293 | void ASN_NULL_template::clean_up() | |
294 | { | |
295 | if (template_selection == VALUE_LIST || | |
296 | template_selection == COMPLEMENTED_LIST) delete [] value_list.list_value; | |
297 | template_selection = UNINITIALIZED_TEMPLATE; | |
298 | } | |
299 | ||
300 | void ASN_NULL_template::copy_template(const ASN_NULL_template& other_value) | |
301 | { | |
302 | switch (other_value.template_selection) { | |
303 | case SPECIFIC_VALUE: | |
304 | case OMIT_VALUE: | |
305 | case ANY_VALUE: | |
306 | case ANY_OR_OMIT: | |
307 | break; | |
308 | case VALUE_LIST: | |
309 | case COMPLEMENTED_LIST: | |
310 | value_list.n_values = other_value.value_list.n_values; | |
311 | value_list.list_value = new ASN_NULL_template[value_list.n_values]; | |
312 | for (unsigned int i = 0; i < value_list.n_values; i++) | |
313 | value_list.list_value[i].copy_template( | |
314 | other_value.value_list.list_value[i]); | |
315 | break; | |
316 | default: | |
317 | TTCN_error("Copying an uninitialized/unsupported template of ASN.1 " | |
318 | "NULL type."); | |
319 | } | |
320 | set_selection(other_value); | |
321 | } | |
322 | ||
323 | ASN_NULL_template::ASN_NULL_template() | |
324 | { | |
325 | ||
326 | } | |
327 | ||
328 | ASN_NULL_template::ASN_NULL_template(template_sel other_value) | |
329 | : Base_Template(other_value) | |
330 | { | |
331 | check_single_selection(other_value); | |
332 | } | |
333 | ||
334 | ASN_NULL_template::ASN_NULL_template(asn_null_type) | |
335 | : Base_Template(SPECIFIC_VALUE) | |
336 | { | |
337 | ||
338 | } | |
339 | ||
340 | ASN_NULL_template::ASN_NULL_template(const ASN_NULL& other_value) | |
341 | : Base_Template(SPECIFIC_VALUE) | |
342 | { | |
343 | if (!other_value.is_bound()) | |
344 | TTCN_error("Creating a template from an unbound ASN.1 NULL value."); | |
345 | } | |
346 | ||
347 | ASN_NULL_template::ASN_NULL_template(const OPTIONAL<ASN_NULL>& other_value) | |
348 | { | |
349 | switch (other_value.get_selection()) { | |
350 | case OPTIONAL_PRESENT: | |
351 | set_selection(SPECIFIC_VALUE); | |
352 | break; | |
353 | case OPTIONAL_OMIT: | |
354 | set_selection(OMIT_VALUE); | |
355 | break; | |
356 | default: | |
357 | TTCN_error("Creating a template of ASN.1 NULL type from an unbound " | |
358 | "optional field."); | |
359 | } | |
360 | } | |
361 | ||
362 | ASN_NULL_template::ASN_NULL_template(const ASN_NULL_template& other_value) | |
363 | : Base_Template() | |
364 | { | |
365 | copy_template(other_value); | |
366 | } | |
367 | ||
368 | ASN_NULL_template::~ASN_NULL_template() | |
369 | { | |
370 | clean_up(); | |
371 | } | |
372 | ||
373 | ASN_NULL_template& ASN_NULL_template::operator=(template_sel other_value) | |
374 | { | |
375 | check_single_selection(other_value); | |
376 | clean_up(); | |
377 | set_selection(other_value); | |
378 | return *this; | |
379 | } | |
380 | ||
381 | ASN_NULL_template& ASN_NULL_template::operator=(asn_null_type) | |
382 | { | |
383 | clean_up(); | |
384 | set_selection(SPECIFIC_VALUE); | |
385 | return *this; | |
386 | } | |
387 | ||
388 | ASN_NULL_template& ASN_NULL_template::operator=(const ASN_NULL& other_value) | |
389 | { | |
390 | if (!other_value.is_bound()) TTCN_error("Assignment of an unbound ASN.1 " | |
391 | "NULL value to a template."); | |
392 | clean_up(); | |
393 | set_selection(SPECIFIC_VALUE); | |
394 | return *this; | |
395 | } | |
396 | ||
397 | ASN_NULL_template& ASN_NULL_template::operator= | |
398 | (const OPTIONAL<ASN_NULL>& other_value) | |
399 | { | |
400 | clean_up(); | |
401 | switch (other_value.get_selection()) { | |
402 | case OPTIONAL_PRESENT: | |
403 | set_selection(SPECIFIC_VALUE); | |
404 | break; | |
405 | case OPTIONAL_OMIT: | |
406 | set_selection(OMIT_VALUE); | |
407 | break; | |
408 | default: | |
409 | TTCN_error("Assignment of an unbound optional field to a template of " | |
410 | "ASN.1 NULL type."); | |
411 | } | |
412 | return *this; | |
413 | } | |
414 | ||
415 | ASN_NULL_template& ASN_NULL_template::operator= | |
416 | (const ASN_NULL_template& other_value) | |
417 | { | |
418 | if (&other_value != this) { | |
419 | clean_up(); | |
420 | copy_template(other_value); | |
421 | } | |
422 | return *this; | |
423 | } | |
424 | ||
425 | boolean ASN_NULL_template::match(asn_null_type other_value) const | |
426 | { | |
427 | switch (template_selection) { | |
428 | case OMIT_VALUE: | |
429 | return FALSE; | |
430 | case SPECIFIC_VALUE: | |
431 | case ANY_VALUE: | |
432 | case ANY_OR_OMIT: | |
433 | return TRUE; | |
434 | case VALUE_LIST: | |
435 | case COMPLEMENTED_LIST: | |
436 | for (unsigned int i = 0; i < value_list.n_values; i++) | |
437 | if (value_list.list_value[i].match(other_value)) | |
438 | return template_selection == VALUE_LIST; | |
439 | return template_selection == COMPLEMENTED_LIST; | |
440 | default: | |
441 | TTCN_error("Matching with an uninitialized/unsupported template of " | |
442 | "ASN.1 NULL type."); | |
443 | } | |
444 | return FALSE; | |
445 | } | |
446 | ||
447 | boolean ASN_NULL_template::match(const ASN_NULL& other_value) const | |
448 | { | |
449 | if (!other_value.is_bound()) return FALSE; | |
450 | return match(ASN_NULL_VALUE); | |
451 | } | |
452 | ||
453 | asn_null_type ASN_NULL_template::valueof() const | |
454 | { | |
455 | if (template_selection != SPECIFIC_VALUE || is_ifpresent) | |
456 | TTCN_error("Performing a valueof " | |
457 | "or send operation on a non-specific template of ASN.1 NULL type."); | |
458 | return ASN_NULL_VALUE; | |
459 | } | |
460 | ||
461 | void ASN_NULL_template::set_type(template_sel template_type, | |
462 | unsigned int list_length) | |
463 | { | |
464 | if (template_type != VALUE_LIST && template_type != COMPLEMENTED_LIST) | |
465 | TTCN_error("Setting an invalid list type for a template of ASN.1 NULL " | |
466 | "type."); | |
467 | clean_up(); | |
468 | set_selection(template_type); | |
469 | value_list.n_values = list_length; | |
470 | value_list.list_value = new ASN_NULL_template[list_length]; | |
471 | } | |
472 | ||
473 | ASN_NULL_template& ASN_NULL_template::list_item(unsigned int list_index) | |
474 | { | |
475 | if (template_selection != VALUE_LIST && | |
476 | template_selection != COMPLEMENTED_LIST) TTCN_error("Accessing a list " | |
477 | "element of a non-list template for ASN.1 NULL type."); | |
478 | if (list_index >= value_list.n_values) | |
479 | TTCN_error("Index overflow in a value list template of ASN.1 NULL type."); | |
480 | return value_list.list_value[list_index]; | |
481 | } | |
482 | ||
483 | void ASN_NULL_template::log() const | |
484 | { | |
485 | switch (template_selection) { | |
486 | case SPECIFIC_VALUE: | |
487 | TTCN_Logger::log_event_str("NULL"); | |
488 | break; | |
489 | case COMPLEMENTED_LIST: | |
490 | TTCN_Logger::log_event_str("complement "); | |
491 | case VALUE_LIST: | |
492 | TTCN_Logger::log_char('('); | |
493 | for (unsigned int i = 0; i < value_list.n_values; i++) { | |
494 | if (i > 0) TTCN_Logger::log_event_str(", "); | |
495 | value_list.list_value[i].log(); | |
496 | } | |
497 | TTCN_Logger::log_char(')'); | |
498 | break; | |
499 | default: | |
500 | log_generic(); | |
501 | } | |
502 | log_ifpresent(); | |
503 | } | |
504 | ||
505 | void ASN_NULL_template::log_match(const ASN_NULL& match_value) const | |
506 | { | |
507 | if(TTCN_Logger::VERBOSITY_COMPACT == TTCN_Logger::get_matching_verbosity()){ | |
508 | TTCN_Logger::print_logmatch_buffer(); | |
509 | TTCN_Logger::log_event_str(" := "); | |
510 | } | |
511 | match_value.log(); | |
512 | TTCN_Logger::log_event_str(" with "); | |
513 | log(); | |
514 | if (match(match_value)) TTCN_Logger::log_event_str(" matched"); | |
515 | else TTCN_Logger::log_event_str(" unmatched"); | |
516 | } | |
517 | ||
518 | void ASN_NULL_template::set_param(Module_Param& param) { | |
519 | param.basic_check(Module_Param::BC_TEMPLATE, "NULL template"); | |
520 | switch (param.get_type()) { | |
521 | case Module_Param::MP_Omit: | |
522 | *this = OMIT_VALUE; | |
523 | break; | |
524 | case Module_Param::MP_Any: | |
525 | *this = ANY_VALUE; | |
526 | break; | |
527 | case Module_Param::MP_AnyOrNone: | |
528 | *this = ANY_OR_OMIT; | |
529 | break; | |
530 | case Module_Param::MP_List_Template: | |
531 | case Module_Param::MP_ComplementList_Template: | |
532 | set_type(param.get_type()==Module_Param::MP_List_Template ? VALUE_LIST : COMPLEMENTED_LIST, param.get_size()); | |
533 | for (size_t i=0; i<param.get_size(); i++) { | |
534 | list_item(i).set_param(*param.get_elem(i)); | |
535 | } | |
536 | break; | |
537 | case Module_Param::MP_Asn_Null: | |
538 | *this = ASN_NULL_VALUE; | |
539 | break; | |
540 | default: | |
541 | param.type_error("NULL template"); | |
542 | } | |
543 | is_ifpresent = param.get_ifpresent(); | |
544 | } | |
545 | ||
546 | void ASN_NULL_template::encode_text(Text_Buf& text_buf) const | |
547 | { | |
548 | encode_text_base(text_buf); | |
549 | switch (template_selection) { | |
550 | case SPECIFIC_VALUE: | |
551 | case OMIT_VALUE: | |
552 | case ANY_VALUE: | |
553 | case ANY_OR_OMIT: | |
554 | break; | |
555 | case VALUE_LIST: | |
556 | case COMPLEMENTED_LIST: | |
557 | text_buf.push_int(value_list.n_values); | |
558 | for (unsigned int i = 0; i < value_list.n_values; i++) | |
559 | value_list.list_value[i].encode_text(text_buf); | |
560 | break; | |
561 | default: | |
562 | TTCN_error("Text encoder: Encoding an undefined/unsupported template " | |
563 | "of ASN.1 NULL type."); | |
564 | } | |
565 | } | |
566 | ||
567 | void ASN_NULL_template::decode_text(Text_Buf& text_buf) | |
568 | { | |
569 | clean_up(); | |
570 | decode_text_base(text_buf); | |
571 | switch (template_selection) { | |
572 | case SPECIFIC_VALUE: | |
573 | case OMIT_VALUE: | |
574 | case ANY_VALUE: | |
575 | case ANY_OR_OMIT: | |
576 | break; | |
577 | case VALUE_LIST: | |
578 | case COMPLEMENTED_LIST: | |
579 | value_list.n_values = text_buf.pull_int().get_val(); | |
580 | value_list.list_value = new ASN_NULL_template[value_list.n_values]; | |
581 | for (unsigned int i = 0; i < value_list.n_values; i++) | |
582 | value_list.list_value[i].decode_text(text_buf); | |
583 | break; | |
584 | default: | |
585 | TTCN_error("Text decoder: An unknown/unsupported selection was received " | |
586 | "in a template for ASN.1 NULL type."); | |
587 | } | |
588 | } | |
589 | ||
590 | boolean ASN_NULL_template::is_present() const | |
591 | { | |
592 | if (template_selection==UNINITIALIZED_TEMPLATE) return FALSE; | |
593 | return !match_omit(); | |
594 | } | |
595 | ||
596 | boolean ASN_NULL_template::match_omit() const | |
597 | { | |
598 | if (is_ifpresent) return TRUE; | |
599 | switch (template_selection) { | |
600 | case OMIT_VALUE: | |
601 | case ANY_OR_OMIT: | |
602 | return TRUE; | |
603 | case VALUE_LIST: | |
604 | case COMPLEMENTED_LIST: | |
605 | for (unsigned int i=0; i<value_list.n_values; i++) | |
606 | if (value_list.list_value[i].match_omit()) | |
607 | return template_selection==VALUE_LIST; | |
608 | return template_selection==COMPLEMENTED_LIST; | |
609 | default: | |
610 | return FALSE; | |
611 | } | |
612 | return FALSE; | |
613 | } | |
614 | ||
615 | #ifndef TITAN_RUNTIME_2 | |
616 | void ASN_NULL_template::check_restriction(template_res t_res, const char* t_name) const | |
617 | { | |
618 | if (template_selection==UNINITIALIZED_TEMPLATE) return; | |
619 | switch ((t_name&&(t_res==TR_VALUE))?TR_OMIT:t_res) { | |
620 | case TR_VALUE: | |
621 | if (!is_ifpresent && template_selection==SPECIFIC_VALUE) return; | |
622 | break; | |
623 | case TR_OMIT: | |
624 | if (!is_ifpresent && (template_selection==OMIT_VALUE || | |
625 | template_selection==SPECIFIC_VALUE)) return; | |
626 | break; | |
627 | case TR_PRESENT: | |
628 | if (!match_omit()) return; | |
629 | break; | |
630 | default: | |
631 | return; | |
632 | } | |
633 | TTCN_error("Restriction `%s' on template of type %s violated.", | |
634 | get_res_name(t_res), t_name ? t_name : "ASN.1 NULL"); | |
635 | } | |
636 | #endif |