Sync with 5.1.0
[deliverable/titan.core.git] / core / Optional.hh
CommitLineData
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#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
25enum optional_sel { OPTIONAL_UNBOUND, OPTIONAL_OMIT, OPTIONAL_PRESENT };
26
27template <typename T_type>
28class 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
50public:
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
69public:
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
87public:
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);
509718e0 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();
970ed795
EL
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
302template<typename T_type>
303Base_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
310template<typename T_type>
311const 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
318template<typename T_type>
319boolean OPTIONAL<T_type>::is_seof() const
320{
321 return (is_present()) ? optional_value->is_seof() : T_type().is_seof();
322}
323
324template<typename T_type>
325const 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
332template<typename T_type>
333OPTIONAL<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
340template<typename T_type>
341OPTIONAL<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
358template<typename T_type> template<typename T_tmp>
359OPTIONAL<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
373template<typename T_type>
374void 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
388template<typename T_type>
389OPTIONAL<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
397template<typename T_type>
398OPTIONAL<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
417template<typename T_type> template <typename T_tmp>
418OPTIONAL<T_type>&
419OPTIONAL<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
438template<typename T_type> template <typename T_tmp>
439OPTIONAL<T_type>&
440OPTIONAL<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
449template<typename T_type>
450boolean 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
461template<typename T_type>
462boolean 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
478template<typename T_type> template <typename T_tmp>
479boolean 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
492template<typename T_type> template <typename T_tmp>
493boolean 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
509template<typename T_type>
510boolean 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
524template<typename T_type>
525boolean 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
539template<typename T_type>
540boolean 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
559template<typename T_type>
560optional_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
572template<typename T_type>
573void 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
588template <typename T_type>
589void 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
600template<typename T_type>
601void 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
616template<typename T_type>
617void 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
625template<typename T_type>
626int 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
640template<typename T_type>
641int 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
670template<typename T_type>
671void 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
678template<typename T_type>
679void OPTIONAL<T_type>::remove_refd_index(int index)
680{
681 --param_refs;
682 optional_value->remove_refd_index(index);
683}
684
509718e0 685template<typename T_type>
686int OPTIONAL<T_type>::size_of()
687{
688 if (!is_present()) {
689 return 0;
690 }
691 return optional_value->size_of();
692}
693
970ed795
EL
694template<typename T_type>
695OPTIONAL<T_type>::operator T_type&()
696{
697 set_to_present();
698 return *optional_value;
699}
700
701template<typename T_type>
702OPTIONAL<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
709template<typename T_type>
710ASN_BER_TLV_t*
711OPTIONAL<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
726template<typename T_type>
727ASN_BER_TLV_t*
728OPTIONAL<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
742template<typename T_type>
743int 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
753template<typename T_type>
754int
755OPTIONAL<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
770template<typename T_type>
771int
772OPTIONAL<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
789template<typename T_type>
790bool
791OPTIONAL<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
820template<typename T_type>
821int
822OPTIONAL<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;
878finished:
879 return 1;
880}
881
882template<typename T_type>
883char ** 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
898template<typename T_type>
899boolean 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
912template<typename T_type>
913boolean 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
920template<typename T_type>
921void 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
932template<typename T_type>
933int 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
942template<typename T_type>
943int 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
952template<typename T_type>
953int 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. */
966template<typename T_type>
967inline boolean operator==(template_sel left_value,
968 const OPTIONAL<T_type>& right_value)
969 { return right_value.is_equal(left_value); }
970
971template<typename T_type>
972inline boolean operator!=(template_sel left_value,
973 const OPTIONAL<T_type>& right_value)
974 { return !right_value.is_equal(left_value); }
975#endif
976
977template<typename T_left, typename T_right>
978inline boolean operator==(const T_left& left_value,
979 const OPTIONAL<T_right>& right_value)
980 { return right_value.is_equal(left_value); }
981
982template<typename T_left, typename T_right>
983inline 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.124605 seconds and 5 git commands to generate.