7c47aacc933cff2f3d826f6256a853b7b204dee7
[deliverable/titan.core.git] / core / Optional.hh
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 #ifndef OPTIONAL_HH
9 #define OPTIONAL_HH
10
11 #include "Types.h"
12 #include "Param_Types.hh"
13 #include "Basetype.hh"
14 #include "Template.hh"
15 #include "BER.hh"
16 #include "Logger.hh"
17 #include "Encdec.hh"
18 #include "Textbuf.hh"
19 #include "Error.hh"
20 #include "Parameters.h"
21 #include "XER.hh"
22 #include "JSON.hh"
23 #include "XmlReader.hh"
24
25 enum optional_sel { OPTIONAL_UNBOUND, OPTIONAL_OMIT, OPTIONAL_PRESENT };
26
27 template <typename T_type>
28 class OPTIONAL : public Base_Type {
29 /** Specifies the state of the optional field
30 * @tricky The optional value can be modified through parameter references,
31 * in which case this member variable will not be updated. Always use the function
32 * get_selection() instead of directly referencing this variable. */
33 optional_sel optional_selection;
34
35 /** The value, if present (owned by OPTIONAL) */
36 T_type *optional_value;
37
38 /** Stores the number of elements referenced by 'out' and 'inout' parameters,
39 * if the optional field is a record of/set of/array.
40 * If at least one element is referenced, the value must not be deleted. */
41 int param_refs;
42
43 /** Set the optional value to present.
44 * If the value was already present, does nothing.
45 * Else allocates a new (uninitialized) T-type.
46 * @post \c optional_selection is OPTIONAL_PRESENT
47 * @post \c optional_value is not NULL
48 */
49 #ifdef TITAN_RUNTIME_2
50 public:
51 virtual
52 #else
53 inline
54 #endif
55 void set_to_present() {
56 if (optional_selection != OPTIONAL_PRESENT) {
57 optional_selection = OPTIONAL_PRESENT;
58 if (optional_value == NULL) {
59 optional_value = new T_type;
60 }
61 }
62 }
63
64 /** Set the optional value to omit.
65 * If the value was present, frees it.
66 * @post optional_selection is OPTIONAL_OMIT
67 */
68 #ifdef TITAN_RUNTIME_2
69 public:
70 virtual
71 #else
72 inline
73 #endif
74 void set_to_omit() {
75 if (is_present()) {
76 if (param_refs > 0) {
77 optional_value->clean_up();
78 }
79 else {
80 delete optional_value;
81 optional_value = NULL;
82 }
83 }
84 optional_selection = OPTIONAL_OMIT;
85 }
86
87 public:
88 /// Default constructor creates an unbound object
89 OPTIONAL() : optional_selection(OPTIONAL_UNBOUND), optional_value(NULL), param_refs(0) { }
90
91 /// Construct an optional object set to omit.
92 /// @p other_value must be OMIT_VALUE, or else dynamic testcase error.
93 OPTIONAL(template_sel other_value);
94
95 /// Copy constructor.
96 /// @note Copying an unbound object creates another unbound object,
97 /// without causing a dynamic test case immediately.
98 OPTIONAL(const OPTIONAL& other_value);
99
100 /// Construct from an optional of different type
101 template <typename T_tmp>
102 OPTIONAL(const OPTIONAL<T_tmp>& other_value);
103
104 /// Construct from an object of different type
105 template <typename T_tmp>
106 OPTIONAL(const T_tmp& other_value)
107 : optional_selection(OPTIONAL_PRESENT),
108 optional_value(new T_type(other_value)),
109 param_refs(0) { }
110
111 ~OPTIONAL()
112 { if (NULL != optional_value) delete optional_value; }
113
114 void clean_up();
115
116 /// Set to omit.
117 /// @p other_value must be OMIT_VALUE, or else dynamic testcase error.
118 OPTIONAL& operator=(template_sel other_value);
119
120 /// Copy assignment
121 OPTIONAL& operator=(const OPTIONAL& other_value);
122
123 /// Assign from an optional of another type
124 template <typename T_tmp>
125 OPTIONAL& operator=(const OPTIONAL<T_tmp>& other_value);
126
127 /// Assign the value
128 template <typename T_tmp>
129 OPTIONAL& operator=(const T_tmp& other_value);
130
131 boolean is_equal(template_sel other_value) const;
132 boolean is_equal(const OPTIONAL& other_value) const;
133 template <typename T_tmp>
134 boolean is_equal(const OPTIONAL<T_tmp>& other_value) const;
135 template <typename T_tmp>
136 boolean is_equal(const T_tmp& other_value) const;
137
138 inline boolean operator==(template_sel other_value) const
139 { return is_equal(other_value); }
140 inline boolean operator!=(template_sel other_value) const
141 { return !is_equal(other_value); }
142 inline boolean operator==(const OPTIONAL& other_value) const
143 { return is_equal(other_value); }
144 inline boolean operator!=(const OPTIONAL& other_value) const
145 { return !is_equal(other_value); }
146 template <typename T_tmp>
147 inline boolean operator==(const T_tmp& other_value) const
148 { return is_equal(other_value); }
149 template <typename T_tmp>
150 inline boolean operator!=(const T_tmp& other_value) const
151 { return !is_equal(other_value); }
152 #ifdef __SUNPRO_CC
153 /* Note: Without these functions the Sun Workshop Pro C++ compiler reports
154 * overloading ambiguity when comparing an optional charstring field with an
155 * optional universal charstring. */
156 template <typename T_tmp>
157 inline boolean operator==(const OPTIONAL<T_tmp>& other_value) const
158 { return is_equal(other_value); }
159 template <typename T_tmp>
160 inline boolean operator!=(const OPTIONAL<T_tmp>& other_value) const
161 { return is_equal(other_value); }
162 #endif
163
164 boolean is_bound() const;
165 boolean is_value() const
166 { return optional_selection == OPTIONAL_PRESENT && optional_value->is_value(); }
167 /** Whether the optional value is present.
168 * @return \c true if optional_selection is OPTIONAL_PRESENT, else \c false */
169 boolean is_present() const;
170
171 #ifdef TITAN_RUNTIME_2
172 /** @name override virtual functions of Base_Type
173 * @{ */
174
175 /** Return \c true (this \b is an optional field) */
176 boolean is_optional() const { return TRUE; }
177
178 /** Access the value for read/write
179 *
180 * @return a pointer to the (modifiable) value
181 * @pre \p optional_selection must be \p OPTIONAL_PRESENT
182 */
183 Base_Type* get_opt_value();
184
185 /** Access the value (read/only)
186 *
187 * @return a pointer to the (const) value
188 * @pre \p optional_selection must be \p OPTIONAL_PRESENT
189 */
190 const Base_Type* get_opt_value() const;
191 boolean is_seof() const;
192 boolean is_equal(const Base_Type* other_value) const { return is_equal(*(static_cast<const OPTIONAL*>(other_value))); }
193 void set_value(const Base_Type* other_value) { *this = *(static_cast<const OPTIONAL*>(other_value)); }
194 Base_Type* clone() const { return new OPTIONAL(*this); }
195 const TTCN_Typedescriptor_t* get_descriptor() const;
196 /** @} */
197 #endif
198
199 /** Whether the value is present.
200 * Note: this is not the TTCN-3 ispresent(), kept for backward compatibility
201 * with the runtime and existing testports which use this version where
202 * unbound errors are caught before causing more trouble
203 *
204 * @return TRUE if the value is present (optional_selection==OPTIONAL_PRESENT)
205 * @return FALSE if the value is not present (optional_selection==OPTIONAL_OMIT)
206 * @pre the value is bound (optional_selection!=OPTIONAL_UNBOUND)
207 */
208 boolean ispresent() const;
209
210 /** @tricky Calculates and returns the actual state of the optional object,
211 * not just the optional_selection member. */
212 optional_sel get_selection() const;
213
214 void log() const;
215 void set_param(Module_Param& param);
216 void encode_text(Text_Buf& text_buf) const;
217 void decode_text(Text_Buf& text_buf);
218
219 #ifdef TITAN_RUNTIME_2
220 virtual int RAW_decode(const TTCN_Typedescriptor_t& td, TTCN_Buffer& buf, int limit,
221 raw_order_t top_bit_ord, boolean no_err=FALSE, int sel_field=-1, boolean first_call=TRUE);
222 #endif
223
224 int XER_encode(const XERdescriptor_t& p_td, TTCN_Buffer& buf, unsigned int flavor, int indent) const;
225 #ifdef TITAN_RUNTIME_2
226 int XER_encode_negtest(const Erroneous_descriptor_t* p_err_descr,
227 const XERdescriptor_t& p_td, TTCN_Buffer& p_buf, unsigned int flavor, int indent) const;
228 #endif
229 /** Used during XML decoding, in case this object is an AnyElement field in a record.
230 * Determines whether XER_decode() should be called or this field should be omitted.
231 * The field should be omitted if:
232 * - the next element in the encoded XML is the next field in the record or
233 * - there are no more elements until the end of the record's XML element.
234 *
235 * @param reader parses the encoded XML
236 * @param next_field_name name of the next field in the record, or null if this is the last one
237 * @param parent_tag_closed true, if the record's XML tag is closed (is an empty element)*/
238 bool XER_check_any_elem(XmlReaderWrap& reader, const char* next_field_name, bool parent_tag_closed);
239 int XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& reader, unsigned int flavor);
240
241 char ** collect_ns(const XERdescriptor_t& p_td, size_t& num, bool& def_ns) const;
242
243 operator T_type&();
244 operator const T_type&() const;
245
246 inline T_type& operator()() { return (T_type&)*this; }
247 inline const T_type& operator()() const { return (const T_type&)*this; }
248
249 ASN_BER_TLV_t* BER_encode_TLV(const TTCN_Typedescriptor_t& p_td,
250 unsigned p_coding) const;
251 #ifdef TITAN_RUNTIME_2
252 ASN_BER_TLV_t* BER_encode_TLV_negtest(const Erroneous_descriptor_t* p_err_descr,
253 const TTCN_Typedescriptor_t& p_td, unsigned p_coding) const;
254 #endif
255 boolean BER_decode_TLV(const TTCN_Typedescriptor_t& p_td,
256 const ASN_BER_TLV_t& p_tlv, unsigned L_form);
257 boolean BER_decode_isMyMsg(const TTCN_Typedescriptor_t& p_td,
258 const ASN_BER_TLV_t& p_tlv);
259 void BER_decode_opentypes(TTCN_Type_list& p_typelist, unsigned L_form);
260
261 #ifdef TITAN_RUNTIME_2
262 int TEXT_encode(const TTCN_Typedescriptor_t&, TTCN_Buffer&) const;
263 int TEXT_encode_negtest(const Erroneous_descriptor_t* p_err_descr,
264 const TTCN_Typedescriptor_t&, TTCN_Buffer&) const;
265 int TEXT_decode(const TTCN_Typedescriptor_t&, TTCN_Buffer&, Limit_Token_List&,
266 boolean no_err=FALSE, boolean first_call=TRUE);
267 #endif
268
269 /** Encodes accordingly to the JSON encoding rules.
270 * Returns the length of the encoded data. */
271 int JSON_encode(const TTCN_Typedescriptor_t&, JSON_Tokenizer&) const;
272
273 /** Decodes accordingly to the JSON encoding rules.
274 * Returns the length of the decoded data. */
275 int JSON_decode(const TTCN_Typedescriptor_t&, JSON_Tokenizer&, boolean);
276
277 /** Called before an element of an optional record of/set of is indexed and passed as an
278 * 'inout' or 'out' parameter to a function.
279 * Sets the optional value to present (this would be done by the indexing operation
280 * anyway) and redirects the call to the optional value. */
281 void add_refd_index(int index);
282
283 /** Called after an element of an optional record of/set of is passed as an
284 * 'inout' or 'out' parameter to a function.
285 * Redirects the call to the optional value. */
286 void remove_refd_index(int index);
287
288 /** Called before an element of an optional record of/set of is passed as an
289 * 'inout' or 'out' parameter to a function. Returns the size of the record of/
290 * set of.
291 * Redirects the call to the optional value. */
292 int size_of();
293 };
294
295 #if HAVE_GCC(4,6)
296 #pragma GCC diagnostic push
297 #pragma GCC diagnostic ignored "-Wswitch-enum"
298 #endif
299
300 #ifdef TITAN_RUNTIME_2
301
302 template<typename T_type>
303 Base_Type* OPTIONAL<T_type>::get_opt_value()
304 {
305 if (!is_present())
306 TTCN_error("Internal error: get_opt_value() called on a non-present optional field.");
307 return optional_value;
308 }
309
310 template<typename T_type>
311 const Base_Type* OPTIONAL<T_type>::get_opt_value() const
312 {
313 if (!is_present())
314 TTCN_error("Internal error: get_opt_value() const called on a non-present optional field.");
315 return optional_value;
316 }
317
318 template<typename T_type>
319 boolean OPTIONAL<T_type>::is_seof() const
320 {
321 return (is_present()) ? optional_value->is_seof() : T_type().is_seof();
322 }
323
324 template<typename T_type>
325 const TTCN_Typedescriptor_t* OPTIONAL<T_type>::get_descriptor() const
326 {
327 return (is_present()) ? optional_value->get_descriptor() : T_type().get_descriptor();
328 }
329
330 #endif
331
332 template<typename T_type>
333 OPTIONAL<T_type>::OPTIONAL(template_sel other_value)
334 : optional_selection(OPTIONAL_OMIT), optional_value(NULL), param_refs(0)
335 {
336 if (other_value != OMIT_VALUE)
337 TTCN_error("Setting an optional field to an invalid value.");
338 }
339
340 template<typename T_type>
341 OPTIONAL<T_type>::OPTIONAL(const OPTIONAL& other_value)
342 : Base_Type(other_value)
343 , optional_selection(other_value.optional_selection)
344 , optional_value(NULL)
345 , param_refs(0)
346 {
347 switch (other_value.optional_selection) {
348 case OPTIONAL_PRESENT:
349 optional_value = new T_type(*other_value.optional_value);
350 break;
351 case OPTIONAL_OMIT:
352 break;
353 default:
354 break;
355 }
356 }
357
358 template<typename T_type> template<typename T_tmp>
359 OPTIONAL<T_type>::OPTIONAL(const OPTIONAL<T_tmp>& other_value)
360 : optional_selection(other_value.get_selection()), optional_value(NULL), param_refs(0)
361 {
362 switch (other_value.get_selection()) {
363 case OPTIONAL_PRESENT:
364 optional_value = new T_type((const T_tmp&)other_value);
365 break;
366 case OPTIONAL_OMIT:
367 break;
368 default:
369 break;
370 }
371 }
372
373 template<typename T_type>
374 void OPTIONAL<T_type>::clean_up()
375 {
376 if (is_present()) {
377 if (param_refs > 0) {
378 optional_value->clean_up();
379 }
380 else {
381 delete optional_value;
382 optional_value = NULL;
383 }
384 }
385 optional_selection = OPTIONAL_UNBOUND;
386 }
387
388 template<typename T_type>
389 OPTIONAL<T_type>& OPTIONAL<T_type>::operator=(template_sel other_value)
390 {
391 if (other_value != OMIT_VALUE)
392 TTCN_error("Internal error: Setting an optional field to an invalid value.");
393 set_to_omit();
394 return *this;
395 }
396
397 template<typename T_type>
398 OPTIONAL<T_type>& OPTIONAL<T_type>::operator=(const OPTIONAL& other_value)
399 {
400 switch (other_value.optional_selection) {
401 case OPTIONAL_PRESENT:
402 optional_selection = OPTIONAL_PRESENT;
403 if (NULL == optional_value) {
404 optional_value = new T_type(*other_value.optional_value);
405 } else *optional_value = *other_value.optional_value;
406 break;
407 case OPTIONAL_OMIT:
408 if (&other_value != this) set_to_omit();
409 break;
410 default:
411 clean_up();
412 break;
413 }
414 return *this;
415 }
416
417 template<typename T_type> template <typename T_tmp>
418 OPTIONAL<T_type>&
419 OPTIONAL<T_type>::operator=(const OPTIONAL<T_tmp>& other_value)
420 {
421 switch (other_value.get_selection()) {
422 case OPTIONAL_PRESENT:
423 optional_selection = OPTIONAL_PRESENT;
424 if (NULL == optional_value) {
425 optional_value = new T_type((const T_tmp&)other_value);
426 } else *optional_value = (const T_tmp&)other_value;
427 break;
428 case OPTIONAL_OMIT:
429 set_to_omit();
430 break;
431 default:
432 clean_up();
433 break;
434 }
435 return *this;
436 }
437
438 template<typename T_type> template <typename T_tmp>
439 OPTIONAL<T_type>&
440 OPTIONAL<T_type>::operator=(const T_tmp& other_value)
441 {
442 optional_selection = OPTIONAL_PRESENT;
443 if (NULL == optional_value) {
444 optional_value = new T_type(other_value);
445 } else *optional_value = other_value;
446 return *this;
447 }
448
449 template<typename T_type>
450 boolean OPTIONAL<T_type>::is_equal(template_sel other_value) const
451 {
452 if (!is_bound()) {
453 if (other_value == UNINITIALIZED_TEMPLATE) return TRUE;
454 TTCN_error("The left operand of comparison is an unbound optional value.");
455 }
456 if (other_value != OMIT_VALUE) TTCN_error("Internal error: The right operand "
457 "of comparison is an invalid value.");
458 return !is_present();
459 }
460
461 template<typename T_type>
462 boolean OPTIONAL<T_type>::is_equal(const OPTIONAL& other_value) const
463 {
464 if (!is_bound()) {
465 if (!other_value.is_bound()) return TRUE;
466 TTCN_error("The left operand of "
467 "comparison is an unbound optional value.");
468 }
469 if (!other_value.is_bound())
470 TTCN_error("The right operand of comparison is an unbound optional value.");
471 boolean present = is_present();
472 if (present != other_value.is_present()) return FALSE;
473 else if (present)
474 return *optional_value == *other_value.optional_value;
475 else return TRUE;
476 }
477
478 template<typename T_type> template <typename T_tmp>
479 boolean OPTIONAL<T_type>::is_equal(const T_tmp& other_value) const
480 {
481 switch (get_selection()) {
482 case OPTIONAL_PRESENT:
483 return *optional_value == other_value;
484 case OPTIONAL_OMIT:
485 return FALSE;
486 default:
487 TTCN_error("The left operand of comparison is an unbound optional value.");
488 }
489 return FALSE;
490 }
491
492 template<typename T_type> template <typename T_tmp>
493 boolean OPTIONAL<T_type>::is_equal(const OPTIONAL<T_tmp>& other_value) const
494 {
495 if (!is_bound()) {
496 if (!other_value.is_bound()) return TRUE;
497 TTCN_error("The left operand of "
498 "comparison is an unbound optional value.");
499 }
500 if (!other_value.is_bound()) TTCN_error("The right operand of "
501 "comparison is an unbound optional value.");
502 boolean present = is_present();
503 if (present != other_value.is_present()) return FALSE;
504 else if (present)
505 return *optional_value == (const T_tmp&)other_value;
506 else return TRUE;
507 }
508
509 template<typename T_type>
510 boolean OPTIONAL<T_type>::is_bound() const
511 {
512 switch (optional_selection) {
513 case OPTIONAL_PRESENT:
514 case OPTIONAL_OMIT:
515 return TRUE;
516 default:
517 if (NULL != optional_value) {
518 return optional_value->is_bound();
519 }
520 return FALSE;
521 }
522 }
523
524 template<typename T_type>
525 boolean OPTIONAL<T_type>::is_present() const
526 {
527 switch (optional_selection) {
528 case OPTIONAL_PRESENT:
529 return TRUE;
530 case OPTIONAL_OMIT:
531 default:
532 if (NULL != optional_value) {
533 return optional_value->is_bound();
534 }
535 return FALSE;
536 }
537 }
538
539 template<typename T_type>
540 boolean OPTIONAL<T_type>::ispresent() const
541 {
542 switch (optional_selection) {
543 case OPTIONAL_PRESENT:
544 return TRUE;
545 case OPTIONAL_OMIT:
546 if (NULL != optional_value) {
547 return optional_value->is_bound();
548 }
549 return FALSE;
550 default:
551 if (NULL != optional_value && optional_value->is_bound()) {
552 return TRUE;
553 }
554 TTCN_error("Using an unbound optional field.");
555 return FALSE;
556 }
557 }
558
559 template<typename T_type>
560 optional_sel OPTIONAL<T_type>::get_selection() const
561 {
562 if (is_present()) {
563 return OPTIONAL_PRESENT;
564 }
565 if (is_bound()) {
566 // not present, but bound => omit
567 return OPTIONAL_OMIT;
568 }
569 return OPTIONAL_UNBOUND;
570 }
571
572 template<typename T_type>
573 void OPTIONAL<T_type>::log() const
574 {
575 switch (get_selection()) {
576 case OPTIONAL_PRESENT:
577 optional_value->log();
578 break;
579 case OPTIONAL_OMIT:
580 TTCN_Logger::log_event_str("omit");
581 break;
582 default:
583 TTCN_Logger::log_event_unbound();
584 break;
585 }
586 }
587
588 template <typename T_type>
589 void OPTIONAL<T_type>::set_param(Module_Param& param) {
590 if (param.get_type()==Module_Param::MP_Omit) {
591 if (param.get_ifpresent()) param.error("An optional field of a record value cannot have an 'ifpresent' attribute");
592 if (param.get_length_restriction()!=NULL) param.error("An optional field of a record value cannot have a length restriction");
593 set_to_omit();
594 return;
595 }
596 set_to_present();
597 optional_value->set_param(param);
598 }
599
600 template<typename T_type>
601 void OPTIONAL<T_type>::encode_text(Text_Buf& text_buf) const
602 {
603 switch (get_selection()) {
604 case OPTIONAL_OMIT:
605 text_buf.push_int((RInt)FALSE);
606 break;
607 case OPTIONAL_PRESENT:
608 text_buf.push_int((RInt)TRUE);
609 optional_value->encode_text(text_buf);
610 break;
611 default:
612 TTCN_error("Text encoder: Encoding an unbound optional value.");
613 }
614 }
615
616 template<typename T_type>
617 void OPTIONAL<T_type>::decode_text(Text_Buf& text_buf)
618 {
619 if (text_buf.pull_int().get_val()) {
620 set_to_present();
621 optional_value->decode_text(text_buf);
622 } else set_to_omit();
623 }
624
625 template<typename T_type>
626 int OPTIONAL<T_type>::JSON_encode(const TTCN_Typedescriptor_t& p_td, JSON_Tokenizer& p_tok) const
627 {
628 switch(get_selection()) {
629 case OPTIONAL_PRESENT:
630 return optional_value->JSON_encode(p_td, p_tok);
631 case OPTIONAL_OMIT:
632 return p_tok.put_next_token(JSON_TOKEN_LITERAL_NULL, NULL);
633 default:
634 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND,
635 "Encoding an unbound optional value.");
636 return -1;
637 }
638 }
639
640 template<typename T_type>
641 int OPTIONAL<T_type>::JSON_decode(const TTCN_Typedescriptor_t& p_td, JSON_Tokenizer& p_tok, boolean p_silent)
642 {
643 size_t buf_pos = p_tok.get_buf_pos();
644 json_token_t token = JSON_TOKEN_NONE;
645 int dec_len = p_tok.get_next_token(&token, NULL, NULL);
646 if (JSON_TOKEN_ERROR == token) {
647 JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_BAD_TOKEN_ERROR, "");
648 dec_len = JSON_ERROR_FATAL;
649 }
650 else if (JSON_TOKEN_LITERAL_NULL == token) {
651 set_to_omit();
652 }
653 else {
654 // read the token again
655 set_to_present();
656 p_tok.set_buf_pos(buf_pos);
657 int ret_val = optional_value->JSON_decode(p_td, p_tok, p_silent);
658 if (0 > ret_val) {
659 if (p_silent) {
660 clean_up();
661 } else {
662 set_to_omit();
663 }
664 }
665 dec_len = ret_val;
666 }
667 return dec_len;
668 }
669
670 template<typename T_type>
671 void OPTIONAL<T_type>::add_refd_index(int index)
672 {
673 ++param_refs;
674 set_to_present();
675 optional_value->add_refd_index(index);
676 }
677
678 template<typename T_type>
679 void OPTIONAL<T_type>::remove_refd_index(int index)
680 {
681 --param_refs;
682 optional_value->remove_refd_index(index);
683 }
684
685 template<typename T_type>
686 int OPTIONAL<T_type>::size_of()
687 {
688 if (!is_present()) {
689 return 0;
690 }
691 return optional_value->size_of();
692 }
693
694 template<typename T_type>
695 OPTIONAL<T_type>::operator T_type&()
696 {
697 set_to_present();
698 return *optional_value;
699 }
700
701 template<typename T_type>
702 OPTIONAL<T_type>::operator const T_type&() const
703 {
704 if (!is_present())
705 TTCN_error("Using the value of an optional field containing omit.");
706 return *optional_value;
707 }
708
709 template<typename T_type>
710 ASN_BER_TLV_t*
711 OPTIONAL<T_type>::BER_encode_TLV(const TTCN_Typedescriptor_t& p_td,
712 unsigned p_coding) const
713 {
714 BER_chk_descr(p_td);
715 switch (get_selection()) {
716 case OPTIONAL_PRESENT:
717 return optional_value->BER_encode_TLV(p_td, p_coding);
718 case OPTIONAL_OMIT:
719 return ASN_BER_TLV_t::construct();
720 default:
721 return ASN_BER_V2TLV(BER_encode_chk_bound(FALSE), p_td, p_coding);
722 }
723 }
724
725 #ifdef TITAN_RUNTIME_2
726 template<typename T_type>
727 ASN_BER_TLV_t*
728 OPTIONAL<T_type>::BER_encode_TLV_negtest(const Erroneous_descriptor_t* p_err_descr,
729 const TTCN_Typedescriptor_t& p_td, unsigned p_coding) const
730 {
731 BER_chk_descr(p_td);
732 switch (get_selection()) {
733 case OPTIONAL_PRESENT:
734 return optional_value->BER_encode_TLV_negtest(p_err_descr, p_td, p_coding);
735 case OPTIONAL_OMIT:
736 return ASN_BER_TLV_t::construct();
737 default:
738 return ASN_BER_V2TLV(BER_encode_chk_bound(FALSE), p_td, p_coding);
739 }
740 }
741
742 template<typename T_type>
743 int OPTIONAL<T_type>::RAW_decode(const TTCN_Typedescriptor_t& p_td,
744 TTCN_Buffer&, int /* limit */, raw_order_t /* top_bit_ord */,
745 boolean /* no_error */, int /* sel_field */, boolean /* first_call */ )
746 {
747 TTCN_error("RAW decoding requested for optional type '%s'"
748 " which has no RAW decoding method.",p_td.name);
749 return 0;
750 }
751 #endif
752
753 template<typename T_type>
754 int
755 OPTIONAL<T_type>::XER_encode(const XERdescriptor_t& p_td, TTCN_Buffer& buf, unsigned int flavor, int indent) const
756 {
757 switch (get_selection()) {
758 case OPTIONAL_PRESENT:
759 return optional_value->XER_encode(p_td, buf, flavor, indent);
760 case OPTIONAL_OMIT:
761 return 0; // nothing to do !
762 default:
763 TTCN_EncDec_ErrorContext::error(
764 TTCN_EncDec::ET_UNBOUND, "Encoding an unbound optional value.");
765 return 0;
766 }
767 }
768
769 #ifdef TITAN_RUNTIME_2
770 template<typename T_type>
771 int
772 OPTIONAL<T_type>::XER_encode_negtest(const Erroneous_descriptor_t* p_err_descr,
773 const XERdescriptor_t& p_td, TTCN_Buffer& buf, unsigned int flavor, int indent) const
774 {
775 switch (get_selection()) {
776 case OPTIONAL_PRESENT:
777 return optional_value->XER_encode_negtest(p_err_descr, p_td, buf, flavor, indent);
778 case OPTIONAL_OMIT:
779 return 0; // nothing to do !
780 default:
781 TTCN_EncDec_ErrorContext::error(
782 TTCN_EncDec::ET_UNBOUND, "Encoding an unbound optional value.");
783 return 0;
784 }
785 }
786 #endif
787
788
789 template<typename T_type>
790 bool
791 OPTIONAL<T_type>::XER_check_any_elem(XmlReaderWrap& reader, const char* next_field_name, bool parent_tag_closed)
792 {
793 // If the record has no elements, then it can't have an AnyElement
794 if (parent_tag_closed) {
795 set_to_omit();
796 return false;
797 }
798
799 while (reader.Ok()) {
800 // Leaving the record before finding an element -> no AnyElement
801 if (XML_READER_TYPE_END_ELEMENT == reader.NodeType()) {
802 set_to_omit();
803 return false;
804 }
805 if (XML_READER_TYPE_ELEMENT == reader.NodeType()) {
806 // The first element found is either the next field's element or the AnyElement
807 if (NULL != next_field_name &&
808 0 == strcmp((const char*)reader.LocalName(), next_field_name)) {
809 set_to_omit();
810 return false;
811 }
812 break;
813 }
814 reader.Read();
815 }
816
817 return true;
818 }
819
820 template<typename T_type>
821 int
822 OPTIONAL<T_type>::XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& reader, unsigned int flavor)
823 {
824 int exer = is_exer(flavor);
825 for (int success = reader.Ok(); success==1; success=reader.Read()) {
826 int type = reader.NodeType();
827 const char * name; // name of the optional field
828 const char * ns_uri;
829
830 if (exer && (p_td.xer_bits & XER_ATTRIBUTE)) {
831 if (XML_READER_TYPE_ATTRIBUTE == type) {
832 for (; success==1; success = reader.MoveToNextAttribute()) {
833 if (!reader.IsNamespaceDecl()) break;
834 }
835
836 name = (const char*)reader.LocalName();
837 if (!check_name(name, p_td, exer)) { // it's not us, bail
838 break;
839 }
840 // we already checked for exer==1
841 if (!check_namespace((const char*)reader.NamespaceUri(), p_td)) break;
842
843 set_to_present();
844 optional_value->XER_decode(p_td, reader, flavor);
845 goto finished;
846 }
847 else break;
848 }
849 else { // not attribute
850 if (XML_READER_TYPE_ELEMENT == type) { // we are at an element
851 name = (const char*)reader.LocalName();
852 ns_uri = (const char*)reader.NamespaceUri();
853 if ((p_td.xer_bits & ANY_ELEMENT) || (exer && (flavor & USE_NIL))
854 || ( (p_td.xer_bits & UNTAGGED) && !reader.IsEmptyElement())
855 // If the optional field (a string) has anyElement, accept the element
856 // regardless of its name. Else the name (and namespace) must match.
857 || T_type::can_start(name, ns_uri, p_td, flavor)) { // it is us
858 found_it:
859 set_to_present();
860 //success = reader.Read(); // move to next thing TODO should it loop till an element ?
861 optional_value->XER_decode(p_td, reader, flavor);
862 }
863 else break; // it's not us, bail
864
865 goto finished;
866 }
867 else if (XML_READER_TYPE_TEXT == type && (flavor & USE_NIL)) {
868 goto found_it;
869 }
870 else if (XML_READER_TYPE_END_ELEMENT == type) {
871 break;
872 }
873 // else circle around
874 } // if attribute
875 } // next
876 set_to_omit();
877 return 0;
878 finished:
879 return 1;
880 }
881
882 template<typename T_type>
883 char ** OPTIONAL<T_type>::collect_ns(const XERdescriptor_t& p_td, size_t& num, bool& def_ns) const {
884 switch (get_selection()) {
885 case OPTIONAL_PRESENT:
886 return optional_value->collect_ns(p_td, num, def_ns);
887 case OPTIONAL_OMIT:
888 def_ns = false;
889 num = 0;
890 return 0;
891 default:
892 TTCN_EncDec_ErrorContext::error(
893 TTCN_EncDec::ET_UNBOUND, "Encoding an unbound value.");
894 return 0;
895 }
896 }
897
898 template<typename T_type>
899 boolean OPTIONAL<T_type>::BER_decode_TLV(const TTCN_Typedescriptor_t& p_td,
900 const ASN_BER_TLV_t& p_tlv,
901 unsigned L_form)
902 {
903 BER_chk_descr(p_td);
904 if (BER_decode_isMyMsg(p_td, p_tlv)) {
905 return optional_value->BER_decode_TLV(p_td, p_tlv, L_form);
906 } else {
907 set_to_omit();
908 return TRUE;
909 }
910 }
911
912 template<typename T_type>
913 boolean OPTIONAL<T_type>::BER_decode_isMyMsg(const TTCN_Typedescriptor_t& p_td,
914 const ASN_BER_TLV_t& p_tlv)
915 {
916 set_to_present();
917 return optional_value->BER_decode_isMyMsg(p_td, p_tlv);
918 }
919
920 template<typename T_type>
921 void OPTIONAL<T_type>::BER_decode_opentypes(TTCN_Type_list& p_typelist,
922 unsigned L_form)
923 {
924 if (is_present()) {
925 optional_selection = OPTIONAL_PRESENT;
926 optional_value->BER_decode_opentypes(p_typelist, L_form);
927 }
928 }
929
930 #ifdef TITAN_RUNTIME_2
931
932 template<typename T_type>
933 int OPTIONAL<T_type>::TEXT_encode(const TTCN_Typedescriptor_t& p_td,
934 TTCN_Buffer& buff) const
935 {
936 if (get_selection())
937 return optional_value->TEXT_encode(p_td, buff);
938 TTCN_error("Internal error: TEXT encoding an unbound/omit optional field.");
939 return 0;
940 }
941
942 template<typename T_type>
943 int OPTIONAL<T_type>::TEXT_encode_negtest(const Erroneous_descriptor_t* p_err_descr,
944 const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& buff) const
945 {
946 if (get_selection())
947 return optional_value->TEXT_encode_negtest(p_err_descr, p_td, buff);
948 TTCN_error("Internal error: TEXT encoding an unbound/omit optional field.");
949 return 0;
950 }
951
952 template<typename T_type>
953 int OPTIONAL<T_type>::TEXT_decode(const TTCN_Typedescriptor_t& p_td,
954 TTCN_Buffer& buff, Limit_Token_List& limit, boolean no_err, boolean first_call)
955 {
956 set_to_present();
957 return optional_value->TEXT_decode(p_td, buff, limit, no_err, first_call);
958 }
959
960 #endif
961
962 #if defined(__GNUC__) && __GNUC__ >= 3
963 /** Note: These functions allow most efficient operation by passing the left
964 * operand OMIT_VALUE as value instead of constant reference.
965 * However, with GCC 2.95.x the functions cause overloading ambiguities. */
966 template<typename T_type>
967 inline boolean operator==(template_sel left_value,
968 const OPTIONAL<T_type>& right_value)
969 { return right_value.is_equal(left_value); }
970
971 template<typename T_type>
972 inline boolean operator!=(template_sel left_value,
973 const OPTIONAL<T_type>& right_value)
974 { return !right_value.is_equal(left_value); }
975 #endif
976
977 template<typename T_left, typename T_right>
978 inline boolean operator==(const T_left& left_value,
979 const OPTIONAL<T_right>& right_value)
980 { return right_value.is_equal(left_value); }
981
982 template<typename T_left, typename T_right>
983 inline boolean operator!=(const T_left& left_value,
984 const OPTIONAL<T_right>& right_value)
985 { return !right_value.is_equal(left_value); }
986
987 #endif
988
989 #if HAVE_GCC(4,6)
990 #pragma GCC diagnostic pop
991 #endif
This page took 0.114233 seconds and 4 git commands to generate.