Create README.md
[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);
287};
288
289#if HAVE_GCC(4,6)
290#pragma GCC diagnostic push
291#pragma GCC diagnostic ignored "-Wswitch-enum"
292#endif
293
294#ifdef TITAN_RUNTIME_2
295
296template<typename T_type>
297Base_Type* OPTIONAL<T_type>::get_opt_value()
298{
299 if (!is_present())
300 TTCN_error("Internal error: get_opt_value() called on a non-present optional field.");
301 return optional_value;
302}
303
304template<typename T_type>
305const Base_Type* OPTIONAL<T_type>::get_opt_value() const
306{
307 if (!is_present())
308 TTCN_error("Internal error: get_opt_value() const called on a non-present optional field.");
309 return optional_value;
310}
311
312template<typename T_type>
313boolean OPTIONAL<T_type>::is_seof() const
314{
315 return (is_present()) ? optional_value->is_seof() : T_type().is_seof();
316}
317
318template<typename T_type>
319const TTCN_Typedescriptor_t* OPTIONAL<T_type>::get_descriptor() const
320{
321 return (is_present()) ? optional_value->get_descriptor() : T_type().get_descriptor();
322}
323
324#endif
325
326template<typename T_type>
327OPTIONAL<T_type>::OPTIONAL(template_sel other_value)
328 : optional_selection(OPTIONAL_OMIT), optional_value(NULL), param_refs(0)
329{
330 if (other_value != OMIT_VALUE)
331 TTCN_error("Setting an optional field to an invalid value.");
332}
333
334template<typename T_type>
335OPTIONAL<T_type>::OPTIONAL(const OPTIONAL& other_value)
336 : Base_Type(other_value)
337 , optional_selection(other_value.optional_selection)
338 , optional_value(NULL)
339 , param_refs(0)
340{
341 switch (other_value.optional_selection) {
342 case OPTIONAL_PRESENT:
343 optional_value = new T_type(*other_value.optional_value);
344 break;
345 case OPTIONAL_OMIT:
346 break;
347 default:
348 break;
349 }
350}
351
352template<typename T_type> template<typename T_tmp>
353OPTIONAL<T_type>::OPTIONAL(const OPTIONAL<T_tmp>& other_value)
354 : optional_selection(other_value.get_selection()), optional_value(NULL), param_refs(0)
355{
356 switch (other_value.get_selection()) {
357 case OPTIONAL_PRESENT:
358 optional_value = new T_type((const T_tmp&)other_value);
359 break;
360 case OPTIONAL_OMIT:
361 break;
362 default:
363 break;
364 }
365}
366
367template<typename T_type>
368void OPTIONAL<T_type>::clean_up()
369{
370 if (is_present()) {
371 if (param_refs > 0) {
372 optional_value->clean_up();
373 }
374 else {
375 delete optional_value;
376 optional_value = NULL;
377 }
378 }
379 optional_selection = OPTIONAL_UNBOUND;
380}
381
382template<typename T_type>
383OPTIONAL<T_type>& OPTIONAL<T_type>::operator=(template_sel other_value)
384{
385 if (other_value != OMIT_VALUE)
386 TTCN_error("Internal error: Setting an optional field to an invalid value.");
387 set_to_omit();
388 return *this;
389}
390
391template<typename T_type>
392OPTIONAL<T_type>& OPTIONAL<T_type>::operator=(const OPTIONAL& other_value)
393{
394 switch (other_value.optional_selection) {
395 case OPTIONAL_PRESENT:
396 optional_selection = OPTIONAL_PRESENT;
397 if (NULL == optional_value) {
398 optional_value = new T_type(*other_value.optional_value);
399 } else *optional_value = *other_value.optional_value;
400 break;
401 case OPTIONAL_OMIT:
402 if (&other_value != this) set_to_omit();
403 break;
404 default:
405 clean_up();
406 break;
407 }
408 return *this;
409}
410
411template<typename T_type> template <typename T_tmp>
412OPTIONAL<T_type>&
413OPTIONAL<T_type>::operator=(const OPTIONAL<T_tmp>& other_value)
414{
415 switch (other_value.get_selection()) {
416 case OPTIONAL_PRESENT:
417 optional_selection = OPTIONAL_PRESENT;
418 if (NULL == optional_value) {
419 optional_value = new T_type((const T_tmp&)other_value);
420 } else *optional_value = (const T_tmp&)other_value;
421 break;
422 case OPTIONAL_OMIT:
423 set_to_omit();
424 break;
425 default:
426 clean_up();
427 break;
428 }
429 return *this;
430}
431
432template<typename T_type> template <typename T_tmp>
433OPTIONAL<T_type>&
434OPTIONAL<T_type>::operator=(const T_tmp& other_value)
435{
436 optional_selection = OPTIONAL_PRESENT;
437 if (NULL == optional_value) {
438 optional_value = new T_type(other_value);
439 } else *optional_value = other_value;
440 return *this;
441}
442
443template<typename T_type>
444boolean OPTIONAL<T_type>::is_equal(template_sel other_value) const
445{
446 if (!is_bound()) {
447 if (other_value == UNINITIALIZED_TEMPLATE) return TRUE;
448 TTCN_error("The left operand of comparison is an unbound optional value.");
449 }
450 if (other_value != OMIT_VALUE) TTCN_error("Internal error: The right operand "
451 "of comparison is an invalid value.");
452 return !is_present();
453}
454
455template<typename T_type>
456boolean OPTIONAL<T_type>::is_equal(const OPTIONAL& other_value) const
457{
458 if (!is_bound()) {
459 if (!other_value.is_bound()) return TRUE;
460 TTCN_error("The left operand of "
461 "comparison is an unbound optional value.");
462 }
463 if (!other_value.is_bound())
464 TTCN_error("The right operand of comparison is an unbound optional value.");
465 boolean present = is_present();
466 if (present != other_value.is_present()) return FALSE;
467 else if (present)
468 return *optional_value == *other_value.optional_value;
469 else return TRUE;
470}
471
472template<typename T_type> template <typename T_tmp>
473boolean OPTIONAL<T_type>::is_equal(const T_tmp& other_value) const
474{
475 switch (get_selection()) {
476 case OPTIONAL_PRESENT:
477 return *optional_value == other_value;
478 case OPTIONAL_OMIT:
479 return FALSE;
480 default:
481 TTCN_error("The left operand of comparison is an unbound optional value.");
482 }
483 return FALSE;
484}
485
486template<typename T_type> template <typename T_tmp>
487boolean OPTIONAL<T_type>::is_equal(const OPTIONAL<T_tmp>& other_value) const
488{
489 if (!is_bound()) {
490 if (!other_value.is_bound()) return TRUE;
491 TTCN_error("The left operand of "
492 "comparison is an unbound optional value.");
493 }
494 if (!other_value.is_bound()) TTCN_error("The right operand of "
495 "comparison is an unbound optional value.");
496 boolean present = is_present();
497 if (present != other_value.is_present()) return FALSE;
498 else if (present)
499 return *optional_value == (const T_tmp&)other_value;
500 else return TRUE;
501}
502
503template<typename T_type>
504boolean OPTIONAL<T_type>::is_bound() const
505{
506 switch (optional_selection) {
507 case OPTIONAL_PRESENT:
508 case OPTIONAL_OMIT:
509 return TRUE;
510 default:
511 if (NULL != optional_value) {
512 return optional_value->is_bound();
513 }
514 return FALSE;
515 }
516}
517
518template<typename T_type>
519boolean OPTIONAL<T_type>::is_present() const
520{
521 switch (optional_selection) {
522 case OPTIONAL_PRESENT:
523 return TRUE;
524 case OPTIONAL_OMIT:
525 default:
526 if (NULL != optional_value) {
527 return optional_value->is_bound();
528 }
529 return FALSE;
530 }
531}
532
533template<typename T_type>
534boolean OPTIONAL<T_type>::ispresent() const
535{
536 switch (optional_selection) {
537 case OPTIONAL_PRESENT:
538 return TRUE;
539 case OPTIONAL_OMIT:
540 if (NULL != optional_value) {
541 return optional_value->is_bound();
542 }
543 return FALSE;
544 default:
545 if (NULL != optional_value && optional_value->is_bound()) {
546 return TRUE;
547 }
548 TTCN_error("Using an unbound optional field.");
549 return FALSE;
550 }
551}
552
553template<typename T_type>
554optional_sel OPTIONAL<T_type>::get_selection() const
555{
556 if (is_present()) {
557 return OPTIONAL_PRESENT;
558 }
559 if (is_bound()) {
560 // not present, but bound => omit
561 return OPTIONAL_OMIT;
562 }
563 return OPTIONAL_UNBOUND;
564}
565
566template<typename T_type>
567void OPTIONAL<T_type>::log() const
568{
569 switch (get_selection()) {
570 case OPTIONAL_PRESENT:
571 optional_value->log();
572 break;
573 case OPTIONAL_OMIT:
574 TTCN_Logger::log_event_str("omit");
575 break;
576 default:
577 TTCN_Logger::log_event_unbound();
578 break;
579 }
580}
581
582template <typename T_type>
583void OPTIONAL<T_type>::set_param(Module_Param& param) {
584 if (param.get_type()==Module_Param::MP_Omit) {
585 if (param.get_ifpresent()) param.error("An optional field of a record value cannot have an 'ifpresent' attribute");
586 if (param.get_length_restriction()!=NULL) param.error("An optional field of a record value cannot have a length restriction");
587 set_to_omit();
588 return;
589 }
590 set_to_present();
591 optional_value->set_param(param);
592}
593
594template<typename T_type>
595void OPTIONAL<T_type>::encode_text(Text_Buf& text_buf) const
596{
597 switch (get_selection()) {
598 case OPTIONAL_OMIT:
599 text_buf.push_int((RInt)FALSE);
600 break;
601 case OPTIONAL_PRESENT:
602 text_buf.push_int((RInt)TRUE);
603 optional_value->encode_text(text_buf);
604 break;
605 default:
606 TTCN_error("Text encoder: Encoding an unbound optional value.");
607 }
608}
609
610template<typename T_type>
611void OPTIONAL<T_type>::decode_text(Text_Buf& text_buf)
612{
613 if (text_buf.pull_int().get_val()) {
614 set_to_present();
615 optional_value->decode_text(text_buf);
616 } else set_to_omit();
617}
618
619template<typename T_type>
620int OPTIONAL<T_type>::JSON_encode(const TTCN_Typedescriptor_t& p_td, JSON_Tokenizer& p_tok) const
621{
622 switch(get_selection()) {
623 case OPTIONAL_PRESENT:
624 return optional_value->JSON_encode(p_td, p_tok);
625 case OPTIONAL_OMIT:
626 return p_tok.put_next_token(JSON_TOKEN_LITERAL_NULL, NULL);
627 default:
628 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND,
629 "Encoding an unbound optional value.");
630 return -1;
631 }
632}
633
634template<typename T_type>
635int OPTIONAL<T_type>::JSON_decode(const TTCN_Typedescriptor_t& p_td, JSON_Tokenizer& p_tok, boolean p_silent)
636{
637 size_t buf_pos = p_tok.get_buf_pos();
638 json_token_t token = JSON_TOKEN_NONE;
639 int dec_len = p_tok.get_next_token(&token, NULL, NULL);
640 if (JSON_TOKEN_ERROR == token) {
641 JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_BAD_TOKEN_ERROR, "");
642 dec_len = JSON_ERROR_FATAL;
643 }
644 else if (JSON_TOKEN_LITERAL_NULL == token) {
645 set_to_omit();
646 }
647 else {
648 // read the token again
649 set_to_present();
650 p_tok.set_buf_pos(buf_pos);
651 int ret_val = optional_value->JSON_decode(p_td, p_tok, p_silent);
652 if (0 > ret_val) {
653 if (p_silent) {
654 clean_up();
655 } else {
656 set_to_omit();
657 }
658 }
659 dec_len = ret_val;
660 }
661 return dec_len;
662}
663
664template<typename T_type>
665void OPTIONAL<T_type>::add_refd_index(int index)
666{
667 ++param_refs;
668 set_to_present();
669 optional_value->add_refd_index(index);
670}
671
672template<typename T_type>
673void OPTIONAL<T_type>::remove_refd_index(int index)
674{
675 --param_refs;
676 optional_value->remove_refd_index(index);
677}
678
679template<typename T_type>
680OPTIONAL<T_type>::operator T_type&()
681{
682 set_to_present();
683 return *optional_value;
684}
685
686template<typename T_type>
687OPTIONAL<T_type>::operator const T_type&() const
688{
689 if (!is_present())
690 TTCN_error("Using the value of an optional field containing omit.");
691 return *optional_value;
692}
693
694template<typename T_type>
695ASN_BER_TLV_t*
696OPTIONAL<T_type>::BER_encode_TLV(const TTCN_Typedescriptor_t& p_td,
697 unsigned p_coding) const
698{
699 BER_chk_descr(p_td);
700 switch (get_selection()) {
701 case OPTIONAL_PRESENT:
702 return optional_value->BER_encode_TLV(p_td, p_coding);
703 case OPTIONAL_OMIT:
704 return ASN_BER_TLV_t::construct();
705 default:
706 return ASN_BER_V2TLV(BER_encode_chk_bound(FALSE), p_td, p_coding);
707 }
708}
709
710#ifdef TITAN_RUNTIME_2
711template<typename T_type>
712ASN_BER_TLV_t*
713OPTIONAL<T_type>::BER_encode_TLV_negtest(const Erroneous_descriptor_t* p_err_descr,
714 const TTCN_Typedescriptor_t& p_td, unsigned p_coding) const
715{
716 BER_chk_descr(p_td);
717 switch (get_selection()) {
718 case OPTIONAL_PRESENT:
719 return optional_value->BER_encode_TLV_negtest(p_err_descr, p_td, p_coding);
720 case OPTIONAL_OMIT:
721 return ASN_BER_TLV_t::construct();
722 default:
723 return ASN_BER_V2TLV(BER_encode_chk_bound(FALSE), p_td, p_coding);
724 }
725}
726
727template<typename T_type>
728int OPTIONAL<T_type>::RAW_decode(const TTCN_Typedescriptor_t& p_td,
729 TTCN_Buffer&, int /* limit */, raw_order_t /* top_bit_ord */,
730 boolean /* no_error */, int /* sel_field */, boolean /* first_call */ )
731{
732 TTCN_error("RAW decoding requested for optional type '%s'"
733 " which has no RAW decoding method.",p_td.name);
734 return 0;
735}
736#endif
737
738template<typename T_type>
739int
740OPTIONAL<T_type>::XER_encode(const XERdescriptor_t& p_td, TTCN_Buffer& buf, unsigned int flavor, int indent) const
741{
742 switch (get_selection()) {
743 case OPTIONAL_PRESENT:
744 return optional_value->XER_encode(p_td, buf, flavor, indent);
745 case OPTIONAL_OMIT:
746 return 0; // nothing to do !
747 default:
748 TTCN_EncDec_ErrorContext::error(
749 TTCN_EncDec::ET_UNBOUND, "Encoding an unbound optional value.");
750 return 0;
751 }
752}
753
754#ifdef TITAN_RUNTIME_2
755template<typename T_type>
756int
757OPTIONAL<T_type>::XER_encode_negtest(const Erroneous_descriptor_t* p_err_descr,
758 const XERdescriptor_t& p_td, TTCN_Buffer& buf, unsigned int flavor, int indent) const
759{
760 switch (get_selection()) {
761 case OPTIONAL_PRESENT:
762 return optional_value->XER_encode_negtest(p_err_descr, p_td, buf, flavor, indent);
763 case OPTIONAL_OMIT:
764 return 0; // nothing to do !
765 default:
766 TTCN_EncDec_ErrorContext::error(
767 TTCN_EncDec::ET_UNBOUND, "Encoding an unbound optional value.");
768 return 0;
769 }
770}
771#endif
772
773
774template<typename T_type>
775bool
776OPTIONAL<T_type>::XER_check_any_elem(XmlReaderWrap& reader, const char* next_field_name, bool parent_tag_closed)
777{
778 // If the record has no elements, then it can't have an AnyElement
779 if (parent_tag_closed) {
780 set_to_omit();
781 return false;
782 }
783
784 while (reader.Ok()) {
785 // Leaving the record before finding an element -> no AnyElement
786 if (XML_READER_TYPE_END_ELEMENT == reader.NodeType()) {
787 set_to_omit();
788 return false;
789 }
790 if (XML_READER_TYPE_ELEMENT == reader.NodeType()) {
791 // The first element found is either the next field's element or the AnyElement
792 if (NULL != next_field_name &&
793 0 == strcmp((const char*)reader.LocalName(), next_field_name)) {
794 set_to_omit();
795 return false;
796 }
797 break;
798 }
799 reader.Read();
800 }
801
802 return true;
803}
804
805template<typename T_type>
806int
807OPTIONAL<T_type>::XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& reader, unsigned int flavor)
808{
809 int exer = is_exer(flavor);
810 for (int success = reader.Ok(); success==1; success=reader.Read()) {
811 int type = reader.NodeType();
812 const char * name; // name of the optional field
813 const char * ns_uri;
814
815 if (exer && (p_td.xer_bits & XER_ATTRIBUTE)) {
816 if (XML_READER_TYPE_ATTRIBUTE == type) {
817 for (; success==1; success = reader.MoveToNextAttribute()) {
818 if (!reader.IsNamespaceDecl()) break;
819 }
820
821 name = (const char*)reader.LocalName();
822 if (!check_name(name, p_td, exer)) { // it's not us, bail
823 break;
824 }
825 // we already checked for exer==1
826 if (!check_namespace((const char*)reader.NamespaceUri(), p_td)) break;
827
828 set_to_present();
829 optional_value->XER_decode(p_td, reader, flavor);
830 goto finished;
831 }
832 else break;
833 }
834 else { // not attribute
835 if (XML_READER_TYPE_ELEMENT == type) { // we are at an element
836 name = (const char*)reader.LocalName();
837 ns_uri = (const char*)reader.NamespaceUri();
838 if ((p_td.xer_bits & ANY_ELEMENT) || (exer && (flavor & USE_NIL))
839 || ( (p_td.xer_bits & UNTAGGED) && !reader.IsEmptyElement())
840 // If the optional field (a string) has anyElement, accept the element
841 // regardless of its name. Else the name (and namespace) must match.
842 || T_type::can_start(name, ns_uri, p_td, flavor)) { // it is us
843 found_it:
844 set_to_present();
845 //success = reader.Read(); // move to next thing TODO should it loop till an element ?
846 optional_value->XER_decode(p_td, reader, flavor);
847 }
848 else break; // it's not us, bail
849
850 goto finished;
851 }
852 else if (XML_READER_TYPE_TEXT == type && (flavor & USE_NIL)) {
853 goto found_it;
854 }
855 else if (XML_READER_TYPE_END_ELEMENT == type) {
856 break;
857 }
858 // else circle around
859 } // if attribute
860 } // next
861 set_to_omit();
862 return 0;
863finished:
864 return 1;
865}
866
867template<typename T_type>
868char ** OPTIONAL<T_type>::collect_ns(const XERdescriptor_t& p_td, size_t& num, bool& def_ns) const {
869 switch (get_selection()) {
870 case OPTIONAL_PRESENT:
871 return optional_value->collect_ns(p_td, num, def_ns);
872 case OPTIONAL_OMIT:
873 def_ns = false;
874 num = 0;
875 return 0;
876 default:
877 TTCN_EncDec_ErrorContext::error(
878 TTCN_EncDec::ET_UNBOUND, "Encoding an unbound value.");
879 return 0;
880 }
881}
882
883template<typename T_type>
884boolean OPTIONAL<T_type>::BER_decode_TLV(const TTCN_Typedescriptor_t& p_td,
885 const ASN_BER_TLV_t& p_tlv,
886 unsigned L_form)
887{
888 BER_chk_descr(p_td);
889 if (BER_decode_isMyMsg(p_td, p_tlv)) {
890 return optional_value->BER_decode_TLV(p_td, p_tlv, L_form);
891 } else {
892 set_to_omit();
893 return TRUE;
894 }
895}
896
897template<typename T_type>
898boolean OPTIONAL<T_type>::BER_decode_isMyMsg(const TTCN_Typedescriptor_t& p_td,
899 const ASN_BER_TLV_t& p_tlv)
900{
901 set_to_present();
902 return optional_value->BER_decode_isMyMsg(p_td, p_tlv);
903}
904
905template<typename T_type>
906void OPTIONAL<T_type>::BER_decode_opentypes(TTCN_Type_list& p_typelist,
907 unsigned L_form)
908{
909 if (is_present()) {
910 optional_selection = OPTIONAL_PRESENT;
911 optional_value->BER_decode_opentypes(p_typelist, L_form);
912 }
913}
914
915#ifdef TITAN_RUNTIME_2
916
917template<typename T_type>
918int OPTIONAL<T_type>::TEXT_encode(const TTCN_Typedescriptor_t& p_td,
919 TTCN_Buffer& buff) const
920{
921 if (get_selection())
922 return optional_value->TEXT_encode(p_td, buff);
923 TTCN_error("Internal error: TEXT encoding an unbound/omit optional field.");
924 return 0;
925}
926
927template<typename T_type>
928int OPTIONAL<T_type>::TEXT_encode_negtest(const Erroneous_descriptor_t* p_err_descr,
929 const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& buff) const
930{
931 if (get_selection())
932 return optional_value->TEXT_encode_negtest(p_err_descr, p_td, buff);
933 TTCN_error("Internal error: TEXT encoding an unbound/omit optional field.");
934 return 0;
935}
936
937template<typename T_type>
938int OPTIONAL<T_type>::TEXT_decode(const TTCN_Typedescriptor_t& p_td,
939 TTCN_Buffer& buff, Limit_Token_List& limit, boolean no_err, boolean first_call)
940{
941 set_to_present();
942 return optional_value->TEXT_decode(p_td, buff, limit, no_err, first_call);
943}
944
945#endif
946
947#if defined(__GNUC__) && __GNUC__ >= 3
948/** Note: These functions allow most efficient operation by passing the left
949 * operand OMIT_VALUE as value instead of constant reference.
950 * However, with GCC 2.95.x the functions cause overloading ambiguities. */
951template<typename T_type>
952inline boolean operator==(template_sel left_value,
953 const OPTIONAL<T_type>& right_value)
954 { return right_value.is_equal(left_value); }
955
956template<typename T_type>
957inline boolean operator!=(template_sel left_value,
958 const OPTIONAL<T_type>& right_value)
959 { return !right_value.is_equal(left_value); }
960#endif
961
962template<typename T_left, typename T_right>
963inline boolean operator==(const T_left& left_value,
964 const OPTIONAL<T_right>& right_value)
965 { return right_value.is_equal(left_value); }
966
967template<typename T_left, typename T_right>
968inline boolean operator!=(const T_left& left_value,
969 const OPTIONAL<T_right>& right_value)
970 { return !right_value.is_equal(left_value); }
971
972#endif
973
974#if HAVE_GCC(4,6)
975#pragma GCC diagnostic pop
976#endif
This page took 0.05715 seconds and 5 git commands to generate.