1 /******************************************************************************
2 * Copyright (c) 2000-2016 Ericsson Telecom AB
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/epl-v10.html
24 * Szabo, Janos Zoltan – initial implementation
28 ******************************************************************************/
31 #include "../common/memory.h"
32 #include "datatypes.h"
37 #include "ttcn3/compiler.h"
39 /** used in the RAW_decode functions generation to store information
40 * about the temporal variables
41 * type is the type of the variable
42 * typedescr is the type's descriptor
43 * start_pos is where the decoding should begin
44 * it is >= 0 if known at compile time, otherwise -1
45 * use_counter stores how many times this type will be used
46 * if it is >1 than we create the variable "globally" so that that
47 * we don't need to create it again in the next component's decode try
48 * if it is ==1 than it is a local variable only referred at one place
49 * we create it only where it is needed, so if at runtime the decoding
50 * comes to a conclusion before the use of this variable, then its
51 * overhead won't slow down the decoding
52 * decoded_for_element is the index of the element in the union for which
53 * this variable was last used for
54 * if it is -1 if the variable hasn't been decoded yet
55 * only in this case it is needed to generate the code to do the decoding
56 * if it is >=0 than we use it generate the conditions
57 * if it doesn't equal to the actual component's index, then we have to
58 * generate the condition and the decoding... parts to it.
59 * if it equals the actual component's index, then we only add its test
60 * to the actual condition
64 const char* typedescr
;
67 int decoded_for_element
;
70 void defUnionClass(struct_def
const *sdef
, output_struct
*output
)
73 const char *name
= sdef
->name
, *dispname
= sdef
->dispname
;
74 const char *at_field
= sdef
->kind
==ANYTYPE
? "AT_" : "";
75 /* at_field is used to prefix the name of accessor member functions
76 * for the anytype, otherwise the generated "INTEGER()" will look like
77 * a constructor, upsetting the C++ compiler. AT_INTEGER() is ok. */
78 char *def
= NULL
, *src
= NULL
;
79 boolean ber_needed
= sdef
->isASN1
&& enable_ber();
80 boolean raw_needed
= sdef
->hasRaw
&& enable_raw();
81 boolean text_needed
= sdef
->hasText
&& enable_text();
82 boolean xer_needed
= sdef
->hasXer
&& enable_xer();
83 boolean json_needed
= sdef
->hasJson
&& enable_json();
85 char *selection_type
, *unbound_value
, *selection_prefix
;
86 selection_type
= mcopystr("union_selection_type");
87 unbound_value
= mcopystr("UNBOUND_VALUE");
88 selection_prefix
= mcopystr("ALT");
91 /* class declaration */
92 output
->header
.class_decls
= mputprintf(output
->header
.class_decls
,
95 /* class definition and source code */
97 /* class header and data fields*/
100 "// written by defUnionClass in " __FILE__
" at %d\n"
102 "class %s : public Base_Type {\n"
107 /* selection type (enum) definition */
108 def
= mputstr(def
, "public:\n"
109 "enum union_selection_type { UNBOUND_VALUE = 0");
110 for (i
= 0; i
< sdef
->nElements
; i
++) {
111 def
= mputprintf(def
, ", ALT_%s = %lu", sdef
->elements
[i
].name
,
112 (unsigned long) (i
+ 1));
114 def
= mputstr(def
, " };\n"
117 def
= mputprintf(def
, "%s union_selection;\n"
118 "union {\n", selection_type
);
119 for (i
= 0; i
< sdef
->nElements
; i
++) {
120 def
= mputprintf(def
, "%s *field_%s;\n", sdef
->elements
[i
].type
,
121 sdef
->elements
[i
].name
);
123 def
= mputstr(def
, "};\n");
125 if(ber_needed
&& sdef
->ot
) {
126 def
=mputstr(def
, "ASN_BER_TLV_t tlv_opentype;\n");
130 def
=mputstr(def
, "Erroneous_descriptor_t* err_descr;\n");
133 /* copy_value function */
134 def
= mputprintf(def
, "void copy_value(const %s& other_value);\n", name
);
135 src
= mputprintf(src
, "void %s::copy_value(const %s& other_value)\n"
137 "switch (other_value.union_selection) {\n", name
, name
);
138 for (i
= 0; i
< sdef
->nElements
; i
++) {
139 src
= mputprintf(src
, "case %s_%s:\n", selection_prefix
, sdef
->elements
[i
].name
);
140 if (legacy_unbound_union_fields
) {
141 src
= mputprintf(src
, "if (other_value.field_%s->is_bound()) ",
142 sdef
->elements
[i
].name
);
144 src
= mputprintf(src
, "field_%s = new %s(*other_value.field_%s);\n",
145 sdef
->elements
[i
].name
, sdef
->elements
[i
].type
, sdef
->elements
[i
].name
);
146 if (legacy_unbound_union_fields
) {
147 src
= mputprintf(src
,
149 "field_%s = new %s;\n"
150 "TTCN_warning(\"Assignment of a union value with an unbound selected "
152 "}\n", sdef
->elements
[i
].name
, sdef
->elements
[i
].type
);
154 src
= mputstr(src
, "break;\n");
156 src
= mputprintf(src
, "default:\n"
157 "TTCN_error(\"Assignment of an unbound union value of type %s.\");\n"
159 "union_selection = other_value.union_selection;\n", dispname
);
162 src
= mputstr(src
, "err_descr = other_value.err_descr;\n");
165 src
= mputstr(src
, "}\n\n");
167 /* default constructor */
168 def
= mputprintf(def
, "\npublic:\n"
170 src
= mputprintf(src
, "%s::%s()%s\n"
172 "union_selection = %s;\n"
174 use_runtime_2
? ": err_descr(NULL)" : "",
177 /* copy constructor */
178 def
= mputprintf(def
, "%s(const %s& other_value);\n", name
, name
);
179 src
= mputprintf(src
, "%s::%s(const %s& other_value)\n"
180 ": Base_Type()" /* call the *default* constructor as before */
182 "copy_value(other_value);\n"
183 "}\n\n", name
, name
, name
);
186 def
= mputprintf(def
, "~%s();\n", name
);
187 src
= mputprintf(src
, "%s::~%s()\n"
190 "}\n\n", name
, name
);
192 /* assignment operator */
193 def
= mputprintf(def
, "%s& operator=(const %s& other_value);\n", name
, name
);
194 src
= mputprintf(src
, "%s& %s::operator=(const %s& other_value)\n"
196 "if (this != &other_value) {\n"
198 "copy_value(other_value);\n"
201 "}\n\n", name
, name
, name
);
203 /* comparison operator */
204 def
= mputprintf(def
, "boolean operator==(const %s& other_value) const;\n",
206 src
= mputprintf(src
, "boolean %s::operator==(const %s& other_value) const\n"
208 "if (union_selection == %s) TTCN_error(\"The left operand of comparison "
209 "is an unbound value of union type %s.\");\n"
210 "if (other_value.union_selection == %s) TTCN_error(\"The right operand of "
211 "comparison is an unbound value of union type %s.\");\n"
212 "if (union_selection != other_value.union_selection) return FALSE;\n"
213 "switch (union_selection) {\n", name
, name
, unbound_value
, dispname
,
214 unbound_value
, dispname
);
215 for (i
= 0; i
< sdef
->nElements
; i
++) {
216 src
= mputprintf(src
, "case %s_%s:\n"
217 "return *field_%s == *other_value.field_%s;\n", selection_prefix
,
218 sdef
->elements
[i
].name
, sdef
->elements
[i
].name
, sdef
->elements
[i
].name
);
220 src
= mputstr(src
, "default:\n"
225 /* != and () operator */
226 def
= mputprintf(def
, "inline boolean operator!=(const %s& other_value) "
227 "const { return !(*this == other_value); }\n", name
);
229 /* field access functions */
230 for (i
= 0; i
< sdef
->nElements
; i
++) {
231 def
= mputprintf(def
, "%s& %s%s();\n", sdef
->elements
[i
].type
,
232 at_field
, sdef
->elements
[i
].name
);
233 src
= mputprintf(src
, "%s& %s::%s%s()\n"
235 "if (union_selection != %s_%s) {\n"
237 "field_%s = new %s;\n"
238 "union_selection = %s_%s;\n"
240 "return *field_%s;\n"
241 "}\n\n", sdef
->elements
[i
].type
, name
, at_field
, sdef
->elements
[i
].name
,
242 selection_prefix
, sdef
->elements
[i
].name
, sdef
->elements
[i
].name
,
243 sdef
->elements
[i
].type
, selection_prefix
, sdef
->elements
[i
].name
,
244 sdef
->elements
[i
].name
);
246 def
= mputprintf(def
, "const %s& %s%s() const;\n", sdef
->elements
[i
].type
,
247 at_field
, sdef
->elements
[i
].name
);
248 src
= mputprintf(src
, "const %s& %s::%s%s() const\n"
250 "if (union_selection != %s_%s) TTCN_error(\"Using non-selected field "
251 "%s in a value of union type %s.\");\n"
252 "return *field_%s;\n"
254 sdef
->elements
[i
].type
, name
, at_field
, sdef
->elements
[i
].name
, selection_prefix
,
255 sdef
->elements
[i
].name
, sdef
->elements
[i
].dispname
, dispname
,
256 sdef
->elements
[i
].name
);
259 /* get_selection function */
260 def
= mputprintf(def
, "inline %s get_selection() const "
261 "{ return union_selection; }\n", selection_type
);
263 /* ischosen function */
264 def
= mputprintf(def
, "boolean ischosen(%s checked_selection) const;\n",
266 src
= mputprintf(src
, "boolean %s::ischosen(%s checked_selection) const\n"
268 "if (checked_selection == %s) TTCN_error(\"Internal error: Performing "
269 "ischosen() operation on an invalid field of union type %s.\");\n"
270 "if (union_selection == %s) TTCN_error(\"Performing ischosen() operation "
271 "on an unbound value of union type %s.\");\n"
272 "return union_selection == checked_selection;\n"
273 "}\n\n", name
, selection_type
, unbound_value
, dispname
, unbound_value
,
276 /* is_bound function */
277 def
= mputstr (def
, "boolean is_bound() const;\n");
278 src
= mputprintf(src
, "boolean %s::is_bound() const\n"
280 " return union_selection != %s;\n"
281 "}\n\n", name
, unbound_value
);
283 /* is_value function */
284 def
= mputstr (def
, "boolean is_value() const;\n");
285 src
= mputprintf(src
, "boolean %s::is_value() const\n"
287 "switch (union_selection) {\n"
288 "case %s: return FALSE;\n",
289 name
, unbound_value
);
290 for (i
= 0; i
< sdef
->nElements
; ++i
) {
291 src
= mputprintf(src
, "case %s_%s: return field_%s->is_value();\n",
292 selection_prefix
, sdef
->elements
[i
].name
, sdef
->elements
[i
].name
);
294 src
= mputstr(src
, "default: TTCN_error(\"Invalid selection in union is_bound\");"
298 /* clean_up function */
299 def
= mputstr (def
, "void clean_up();\n");
300 src
= mputprintf(src
, "void %s::clean_up()\n"
302 "switch (union_selection) {\n",
304 for (i
= 0; i
< sdef
->nElements
; ++i
) {
305 src
= mputprintf(src
, "case %s_%s:\n"
306 " delete field_%s;\n"
308 selection_prefix
, sdef
->elements
[i
].name
, sdef
->elements
[i
].name
);
310 src
= mputprintf(src
, "default:\n"
313 "union_selection = %s;\n"
314 "}\n\n", unbound_value
);
318 "boolean is_equal(const Base_Type* other_value) const;\n"
319 "void set_value(const Base_Type* other_value);\n"
320 "Base_Type* clone() const;\n"
321 "const TTCN_Typedescriptor_t* get_descriptor() const;\n"
322 "void set_err_descr(Erroneous_descriptor_t* p_err_descr) { err_descr=p_err_descr; }\n"
323 "Erroneous_descriptor_t* get_err_descr() const { return err_descr; }\n");
324 src
= mputprintf(src
,
325 "boolean %s::is_equal(const Base_Type* other_value) const "
326 "{ return *this == *(static_cast<const %s*>(other_value)); }\n"
327 "void %s::set_value(const Base_Type* other_value) "
328 "{ *this = *(static_cast<const %s*>(other_value)); }\n"
329 "Base_Type* %s::clone() const { return new %s(*this); }\n"
330 "const TTCN_Typedescriptor_t* %s::get_descriptor() const "
331 "{ return &%s_descr_; }\n",
338 "inline boolean is_present() const { return is_bound(); }\n");
342 def
= mputstr(def
, "void log() const;\n");
343 src
= mputprintf(src
, "void %s::log() const\n"
345 "switch (union_selection) {\n", name
);
346 for (i
= 0; i
< sdef
->nElements
; i
++) {
347 src
= mputprintf(src
, "case %s_%s:\n"
348 "TTCN_Logger::log_event_str(\"{ %s := \");\n"
350 "TTCN_Logger::log_event_str(\" }\");\n"
351 "break;\n", selection_prefix
, sdef
->elements
[i
].name
,
352 sdef
->elements
[i
].dispname
, sdef
->elements
[i
].name
);
354 src
= mputstr(src
, "default:\n"
355 "TTCN_Logger::log_event_unbound();\n"
358 src
= mputstr(src
, "if (err_descr) err_descr->log();\n");
360 src
= mputstr(src
, "}\n\n");
362 /* set_param function */
363 def
= mputstr(def
, "void set_param(Module_Param& param);\n");
364 src
= mputprintf(src
, "void %s::set_param(Module_Param& param)\n"
366 " if (dynamic_cast<Module_Param_Name*>(param.get_id()) != NULL &&\n"
367 " param.get_id()->next_name()) {\n"
368 // Haven't reached the end of the module parameter name
369 // => the name refers to one of the fields, not to the whole union
370 " char* param_field = param.get_id()->get_current_name();\n"
371 " if (param_field[0] >= '0' && param_field[0] <= '9') {\n"
372 " param.error(\"Unexpected array index in module parameter, expected a valid field\"\n"
373 " \" name for union type `%s'\");\n"
375 " ", name
, dispname
);
376 for (i
= 0; i
< sdef
->nElements
; i
++) {
377 src
= mputprintf(src
,
378 "if (strcmp(\"%s\", param_field) == 0) {\n"
379 " %s%s().set_param(param);\n"
382 sdef
->elements
[i
].dispname
, at_field
, sdef
->elements
[i
].name
);
384 src
= mputprintf(src
,
385 "param.error(\"Field `%%s' not found in union type `%s'\", param_field);\n"
387 " param.basic_check(Module_Param::BC_VALUE, \"union value\");\n"
388 " Module_Param_Ptr m_p = ¶m;\n"
389 " if (param.get_type() == Module_Param::MP_Reference) {\n"
390 " m_p = param.get_referenced_param();\n"
392 " if (m_p->get_type()==Module_Param::MP_Value_List && m_p->get_size()==0) return;\n"
393 " if (m_p->get_type()!=Module_Param::MP_Assignment_List) {\n"
394 " param.error(\"union value with field name was expected\");\n"
396 " Module_Param* mp_last = m_p->get_elem(m_p->get_size()-1);\n", dispname
);
398 for (i
= 0; i
< sdef
->nElements
; i
++) {
399 src
= mputprintf(src
,
400 " if (!strcmp(mp_last->get_id()->get_name(), \"%s\")) {\n"
401 " %s%s().set_param(*mp_last);\n"
402 " if (!%s%s().is_bound()) "
403 , sdef
->elements
[i
].dispname
, at_field
, sdef
->elements
[i
].name
404 , at_field
, sdef
->elements
[i
].name
);
405 if (legacy_unbound_union_fields
) {
406 src
= mputprintf(src
,
407 "TTCN_warning(\"Alternative '%s' was selected for union of type '%s', "
408 "but its value is unbound\");\n"
409 , sdef
->elements
[i
].dispname
, sdef
->dispname
);
412 // a union's alternative cannot be unbound
413 src
= mputstr(src
, "clean_up();\n");
419 src
= mputprintf(src
,
420 " mp_last->error(\"Field %%s does not exist in type %s.\", mp_last->get_id()->get_name());\n"
423 /* get param function */
424 def
= mputstr(def
, "Module_Param* get_param(Module_Param_Name& param_name) const;\n");
425 src
= mputprintf(src
,
426 "Module_Param* %s::get_param(Module_Param_Name& param_name) const\n"
428 " if (!is_bound()) {\n"
429 " return new Module_Param_Unbound();\n"
431 " if (param_name.next_name()) {\n"
432 // Haven't reached the end of the module parameter name
433 // => the name refers to one of the fields, not to the whole union
434 " char* param_field = param_name.get_current_name();\n"
435 " if (param_field[0] >= '0' && param_field[0] <= '9') {\n"
436 " TTCN_error(\"Unexpected array index in module parameter reference, \"\n"
437 " \"expected a valid field name for union type `%s'\");\n"
439 " ", name
, dispname
);
440 for (i
= 0; i
< sdef
->nElements
; i
++) {
441 src
= mputprintf(src
,
442 "if (strcmp(\"%s\", param_field) == 0) {\n"
443 " return %s%s().get_param(param_name);\n"
445 sdef
->elements
[i
].dispname
, at_field
, sdef
->elements
[i
].name
);
447 src
= mputprintf(src
,
448 "TTCN_error(\"Field `%%s' not found in union type `%s'\", param_field);\n"
450 " Module_Param* mp_field = NULL;\n"
451 " switch(union_selection) {\n"
453 for (i
= 0; i
< sdef
->nElements
; ++i
) {
454 src
= mputprintf(src
,
456 " mp_field = field_%s->get_param(param_name);\n"
457 " mp_field->set_id(new Module_Param_FieldName(mcopystr(\"%s\")));\n"
459 , selection_prefix
, sdef
->elements
[i
].name
460 , sdef
->elements
[i
].name
, sdef
->elements
[i
].dispname
);
466 " Module_Param_Assignment_List* m_p = new Module_Param_Assignment_List();\n"
467 " m_p->add_elem(mp_field);\n"
471 /* set implicit omit function, recursive */
472 def
= mputstr(def
, " void set_implicit_omit();\n");
473 src
= mputprintf(src
,
474 "void %s::set_implicit_omit()\n{\n"
475 "switch (union_selection) {\n", name
);
476 for (i
= 0; i
< sdef
->nElements
; i
++) {
477 src
= mputprintf(src
,
479 "field_%s->set_implicit_omit(); break;\n",
480 selection_prefix
, sdef
->elements
[i
].name
, sdef
->elements
[i
].name
);
482 src
= mputstr(src
, "default: break;\n}\n}\n\n");
484 /* encode_text function */
485 def
= mputstr(def
, "void encode_text(Text_Buf& text_buf) const;\n");
486 src
= mputprintf(src
, "void %s::encode_text(Text_Buf& text_buf) const\n"
488 "text_buf.push_int(union_selection);\n"
489 "switch (union_selection) {\n", name
);
490 for (i
= 0; i
< sdef
->nElements
; i
++) {
491 src
= mputprintf(src
, "case %s_%s:\n"
492 "field_%s->encode_text(text_buf);\n"
493 "break;\n", selection_prefix
, sdef
->elements
[i
].name
,
494 sdef
->elements
[i
].name
);
496 src
= mputprintf(src
, "default:\n"
497 "TTCN_error(\"Text encoder: Encoding an unbound value of union type "
502 /* decode_text function */
503 def
= mputstr(def
, "void decode_text(Text_Buf& text_buf);\n");
504 src
= mputprintf(src
, "void %s::decode_text(Text_Buf& text_buf)\n"
506 "switch ((%s)text_buf.pull_int().get_val()) {\n", name
, selection_type
);
507 for (i
= 0; i
< sdef
->nElements
; i
++) {
508 src
= mputprintf(src
, "case %s_%s:\n"
509 "%s%s().decode_text(text_buf);\n"
510 "break;\n", selection_prefix
, sdef
->elements
[i
].name
,
511 at_field
, sdef
->elements
[i
].name
);
513 src
= mputprintf(src
, "default:\n"
514 "TTCN_error(\"Text decoder: Unrecognized union selector was received "
519 if(ber_needed
|| raw_needed
|| text_needed
|| xer_needed
|| json_needed
)
520 def_encdec(name
, &def
, &src
, ber_needed
, raw_needed
, text_needed
,
521 xer_needed
, json_needed
, TRUE
);
525 def
= mputstr(def
, "private:\n"
526 "boolean BER_decode_set_selection(const ASN_BER_TLV_t& p_tlv);\n"
528 "boolean BER_decode_isMyMsg(const TTCN_Typedescriptor_t& p_td, "
529 "const ASN_BER_TLV_t& p_tlv);\n");
531 /* BER_encode_TLV() */
532 src
= mputprintf(src
,
534 "// written by %s in " __FILE__
" at %d\n"
536 "ASN_BER_TLV_t *%s::BER_encode_TLV("
537 "const TTCN_Typedescriptor_t& p_td, unsigned p_coding) const\n"
540 , __FUNCTION__
, __LINE__
545 " if (err_descr) return BER_encode_TLV_negtest(err_descr, p_td, p_coding);\n");
548 " BER_chk_descr(p_td);\n"
549 " ASN_BER_TLV_t *new_tlv;\n"
550 " TTCN_EncDec_ErrorContext ec_0(\"Alternative '\");\n"
551 " TTCN_EncDec_ErrorContext ec_1;\n"
552 " switch (union_selection) {\n");
553 for (i
= 0; i
< sdef
->nElements
; i
++) {
554 src
= mputprintf(src
, " case %s_%s:\n"
555 " ec_1.set_msg(\"%s': \");\n"
556 " new_tlv = field_%s->BER_encode_TLV(%s_descr_, p_coding);\n"
557 " break;\n", selection_prefix
, sdef
->elements
[i
].name
,
558 sdef
->elements
[i
].dispname
,
559 sdef
->elements
[i
].name
, sdef
->elements
[i
].typedescrname
);
561 src
= mputprintf(src
, " case %s:\n"
562 " new_tlv = BER_encode_chk_bound(FALSE);\n"
565 " TTCN_EncDec_ErrorContext::error_internal(\"Unknown selection.\");\n"
568 " return ASN_BER_V2TLV(new_tlv, p_td, p_coding);\n"
569 "}\n\n", unbound_value
);
571 if (use_runtime_2
) { /* BER_encode_TLV_negtest() */
573 "ASN_BER_TLV_t* BER_encode_TLV_negtest(const Erroneous_descriptor_t* p_err_descr, const TTCN_Typedescriptor_t& p_td, unsigned p_coding) const;\n");
574 src
= mputprintf(src
,
575 "ASN_BER_TLV_t *%s::BER_encode_TLV_negtest(const Erroneous_descriptor_t* p_err_descr, "
576 "const TTCN_Typedescriptor_t& p_td, unsigned p_coding) const\n"
578 " BER_chk_descr(p_td);\n"
579 " ASN_BER_TLV_t *new_tlv = NULL;\n"
580 " TTCN_EncDec_ErrorContext ec_0(\"Alternative '\");\n"
581 " TTCN_EncDec_ErrorContext ec_1;\n"
582 " const Erroneous_values_t* err_vals = NULL;\n"
583 " const Erroneous_descriptor_t* emb_descr = NULL;\n"
584 " switch (union_selection) {\n", name
);
585 for (i
= 0; i
< sdef
->nElements
; i
++) {
586 src
= mputprintf(src
, " case %s_%s:\n"
587 " err_vals = p_err_descr->get_field_err_values(%d);\n"
588 " emb_descr = p_err_descr->get_field_emb_descr(%d);\n"
589 " if (err_vals && err_vals->value) {\n"
590 " if (err_vals->value->errval) {\n"
591 " ec_1.set_msg(\"%s'(erroneous value): \");\n"
592 " if (err_vals->value->raw) {\n"
593 " new_tlv = err_vals->value->errval->BER_encode_negtest_raw();\n"
595 " if (err_vals->value->type_descr==NULL) TTCN_error(\"internal error: erroneous value typedescriptor missing\");\n"
596 " new_tlv = err_vals->value->errval->BER_encode_TLV(*err_vals->value->type_descr, p_coding);\n"
600 " ec_1.set_msg(\"%s': \");\n"
601 " if (emb_descr) new_tlv = field_%s->BER_encode_TLV_negtest(emb_descr, %s_descr_, p_coding);\n"
602 " else new_tlv = field_%s->BER_encode_TLV(%s_descr_, p_coding);\n"
604 " break;\n", selection_prefix
, sdef
->elements
[i
].name
,
605 (int)i
, (int)i
, sdef
->elements
[i
].dispname
, sdef
->elements
[i
].dispname
,
606 sdef
->elements
[i
].name
, sdef
->elements
[i
].typedescrname
,
607 sdef
->elements
[i
].name
, sdef
->elements
[i
].typedescrname
);
609 src
= mputprintf(src
, " case %s:\n"
610 " new_tlv = BER_encode_chk_bound(FALSE);\n"
613 " TTCN_EncDec_ErrorContext::error_internal(\"Unknown selection.\");\n"
616 " if (new_tlv==NULL) new_tlv=ASN_BER_TLV_t::construct(NULL);\n"
617 " return ASN_BER_V2TLV(new_tlv, p_td, p_coding);\n"
618 "}\n\n", unbound_value
);
621 /* BER_decode_set_selection() */
622 src
= mputprintf(src
, "boolean %s::BER_decode_set_selection("
623 "const ASN_BER_TLV_t& p_tlv)\n"
625 " clean_up();\n", name
);
626 for (i
= 0; i
< sdef
->nElements
; i
++) {
627 src
= mputprintf(src
, " field_%s = new %s;\n"
628 " union_selection = %s_%s;\n"
629 " if (field_%s->BER_decode_isMyMsg(%s_descr_, p_tlv)) return TRUE;\n"
630 " delete field_%s;\n", sdef
->elements
[i
].name
, sdef
->elements
[i
].type
,
631 selection_prefix
, sdef
->elements
[i
].name
, sdef
->elements
[i
].name
,
632 sdef
->elements
[i
].typedescrname
, sdef
->elements
[i
].name
);
634 src
= mputprintf(src
, " union_selection = %s;\n"
636 "}\n\n", unbound_value
);
638 /* BER_decode_isMyMsg() */
639 src
= mputprintf(src
, "boolean %s::BER_decode_isMyMsg("
640 "const TTCN_Typedescriptor_t& p_td, const ASN_BER_TLV_t& p_tlv)\n"
642 " if (p_td.ber->n_tags == 0) {\n"
644 " return tmp_type.BER_decode_set_selection(p_tlv);\n"
645 " } else return Base_Type::BER_decode_isMyMsg(p_td, p_tlv);\n"
646 "}\n\n", name
, name
);
648 /* BER_decode_TLV() */
649 src
= mputprintf(src
, "boolean %s::BER_decode_TLV("
650 "const TTCN_Typedescriptor_t& p_td, const ASN_BER_TLV_t& p_tlv, "
653 " BER_chk_descr(p_td);\n"
654 " ASN_BER_TLV_t stripped_tlv;\n"
655 " BER_decode_strip_tags(*p_td.ber, p_tlv, L_form, stripped_tlv);\n"
656 " TTCN_EncDec_ErrorContext ec_0(\"While decoding '%s' type: \");\n",
659 src
= mputprintf(src
, " if (!BER_decode_TLV_CHOICE(*p_td.ber, "
660 "stripped_tlv, L_form, tlv_opentype)) {\n"
661 " tlv_opentype.Tlen = 0;\n"
665 " union_selection = %s;\n", unbound_value
);
667 src
= mputstr(src
, " ASN_BER_TLV_t tmp_tlv;\n"
668 " if (!BER_decode_TLV_CHOICE(*p_td.ber, stripped_tlv, L_form, "
670 "!BER_decode_CHOICE_selection(BER_decode_set_selection(tmp_tlv), "
671 "tmp_tlv)) return FALSE;\n"
672 " TTCN_EncDec_ErrorContext ec_1(\"Alternative '\");\n"
673 " TTCN_EncDec_ErrorContext ec_2;\n"
674 " switch (union_selection) {\n");
675 for(i
= 0; i
< sdef
->nElements
; i
++) {
676 src
= mputprintf(src
, " case %s_%s:\n"
677 " ec_2.set_msg(\"%s': \");\n"
678 " field_%s->BER_decode_TLV(%s_descr_, tmp_tlv, L_form);\n"
679 " break;\n", selection_prefix
, sdef
->elements
[i
].name
,
680 sdef
->elements
[i
].dispname
,
681 sdef
->elements
[i
].name
, sdef
->elements
[i
].typedescrname
);
683 src
= mputstr(src
, " default:\n"
686 if (sdef
->opentype_outermost
) {
688 " TTCN_EncDec_ErrorContext ec_1(\"While decoding opentypes: \");\n"
689 " TTCN_Type_list p_typelist;\n"
690 " BER_decode_opentypes(p_typelist, L_form);\n");
691 } /* if sdef->opentype_outermost */
693 src
= mputstr(src
, " return TRUE;\n"
696 if (sdef
->ot
|| sdef
->has_opentypes
) { /* theoretically, these are
698 /* BER_decode_opentypes() */
699 def
= mputstr(def
, "void BER_decode_opentypes("
700 "TTCN_Type_list& p_typelist, unsigned L_form);\n");
701 src
= mputprintf(src
, "void %s::BER_decode_opentypes("
702 "TTCN_Type_list& p_typelist, unsigned L_form)\n"
705 AtNotationList_t
*anl
= &sdef
->ot
->anl
;
706 OpentypeAlternativeList_t
*oal
= &sdef
->ot
->oal
;
707 src
= mputprintf(src
,
708 " if (union_selection != %s) return;\n"
709 " TTCN_EncDec_ErrorContext ec_0(\"While decoding open type '%s': "
710 "\");\n", unbound_value
, dispname
);
711 if (oal
->nElements
> 0) {
714 /* variable declarations - the referenced components */
715 for (anl_i
= 0; anl_i
< anl
->nElements
; anl_i
++) {
716 AtNotation_t
*an
= anl
->elements
+ anl_i
;
717 src
= mputprintf(src
, " const %s& f_%lu = static_cast<const %s*>"
718 "(p_typelist.get_nth(%lu))->%s;\n", an
->type_name
,
719 (unsigned long) (anl_i
+ 1), an
->parent_typename
,
720 (unsigned long) an
->parent_level
, an
->sourcecode
);
722 src
= mputstr(src
, " {\n"
723 " TTCN_EncDec_ErrorContext ec_1(\"Alternative '\");\n"
724 " TTCN_EncDec_ErrorContext ec_2;\n");
725 s2
= mprintf("%*s", (int)(anl
->nElements
+ 2) * 2, "");
726 for (oal_i
= 0; oal_i
< oal
->nElements
; oal_i
++) {
728 OpentypeAlternative_t
*oa
= oal
->elements
+ oal_i
;
730 for (if_level
= 0; if_level
< anl
->nElements
; if_level
++)
731 if (oa
->const_valuenames
[if_level
]) break;
732 for (i
= anl
->nElements
; i
> if_level
; i
--)
733 src
= mputprintf(src
, "%*s}\n", (int)(i
+ 1) * 2, "");
736 for (anl_i
= if_level
; anl_i
< anl
->nElements
; anl_i
++) {
737 src
= mputprintf(src
, "%*s%sif (f_%lu == %s) {\n",
738 (int)(anl_i
+ 2) * 2, "",
739 oal_i
&& anl_i
<= if_level
? "else " : "",
740 (unsigned long) (anl_i
+ 1), oa
->const_valuenames
[anl_i
]);
742 src
= mputprintf(src
, "%sunion_selection = %s_%s;\n"
743 "%sfield_%s = new %s;\n"
744 "%sec_2.set_msg(\"%s': \");\n"
745 "%sfield_%s->BER_decode_TLV(%s_descr_, tlv_opentype, L_form);\n",
746 s2
, selection_prefix
, oa
->alt
, s2
, oa
->alt
, oa
->alt_typename
, s2
,
747 oa
->alt_dispname
, s2
, oa
->alt
, oa
->alt_typedescrname
);
750 if (oal
->nElements
> 0)
751 for (i
= anl
->nElements
; i
> 0; i
--)
752 src
= mputprintf(src
, "%*s}\n", (int)(i
+1)*2, "");
753 src
= mputprintf(src
, " }\n"
754 " if (union_selection == %s) {\n"
755 " ec_0.error(TTCN_EncDec::ET_DEC_OPENTYPE, \"Cannot decode "
756 "open type: broken component relation constraint.\");\n"
757 " if (TTCN_EncDec::get_error_behavior("
758 "TTCN_EncDec::ET_DEC_OPENTYPE) != TTCN_EncDec::EB_IGNORE) {\n"
759 " TTCN_Logger::log_str(TTCN_WARNING, \"The value%s of"
760 " constraining component%s:\");\n", unbound_value
,
761 anl
->nElements
> 1 ? "s" : "", anl
->nElements
> 1 ? "s" : "");
762 for (anl_i
= 0; anl_i
< anl
->nElements
; anl_i
++) {
763 AtNotation_t
*an
= anl
->elements
+ anl_i
;
764 src
= mputprintf(src
,
765 " TTCN_Logger::begin_event(TTCN_WARNING);\n"
766 " TTCN_Logger::log_event_str(\"Component '%s': \");\n"
768 " TTCN_Logger::end_event();\n", an
->dispname
,
769 (unsigned long) (anl_i
+ 1));
771 src
= mputstr(src
, " }\n"
773 } /* if oal->nElements>0 */
775 src
= mputstr(src
, " ec_0.error(TTCN_EncDec::ET_DEC_OPENTYPE, "
776 "\"Cannot decode open type: the constraining object set is "
778 } /* oal->nElements==0 */
780 else { /* if !sdef->ot (but has_opentypes) */
782 " p_typelist.push(this);\n"
783 " TTCN_EncDec_ErrorContext ec_0(\"Alternative '\");\n"
784 " TTCN_EncDec_ErrorContext ec_1;\n"
785 " switch (union_selection) {\n");
786 for (i
= 0; i
< sdef
->nElements
; i
++) {
787 src
= mputprintf(src
, " case %s_%s:\n"
788 " ec_1.set_msg(\"%s': \");\n"
789 " field_%s->BER_decode_opentypes(p_typelist, L_form);\n"
790 " break;\n", selection_prefix
, sdef
->elements
[i
].name
,
791 sdef
->elements
[i
].dispname
, sdef
->elements
[i
].name
);
793 src
= mputstr(src
, " default:\n"
796 " p_typelist.pop();\n");
797 } /* if has opentypes */
798 src
= mputstr(src
, "}\n"
800 } /* if sdef->ot || sdef->has_opentypes */
801 } /* if ber_needed */
804 size_t nTemp_variables
= 0;
805 temporal_variable
* temp_variable_list
= NULL
;
806 int* tag_type
= (int*) Malloc(sdef
->nElements
*sizeof(int));
807 memset(tag_type
, 0, sdef
->nElements
* sizeof(int));
808 if (sdef
->hasRaw
) { /* fill tag_type. 0-No tag, >0 index of the tag + 1 */
809 for (i
= 0; i
< sdef
->raw
.taglist
.nElements
; i
++) {
810 if (sdef
->raw
.taglist
.list
[i
].nElements
) {
811 boolean found
= FALSE
;
813 for (v
= 0; v
< sdef
->raw
.taglist
.list
[i
].nElements
; v
++) {
814 if (sdef
->raw
.taglist
.list
[i
].fields
[v
].start_pos
>= 0) {
820 tag_type
[sdef
->raw
.taglist
.list
[i
].fieldnum
] = i
+ 1;
822 tag_type
[sdef
->raw
.taglist
.list
[i
].fieldnum
] = -i
- 1;
826 src
= mputprintf(src
, "int %s::RAW_decode(\n"
827 "const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf, int limit, \n"
828 "raw_order_t top_bit_ord, boolean no_err, int sel_field, boolean)\n"
830 " int prepaddlength=p_buf.increase_pos_padd(p_td.raw->prepadding);\n"
831 " limit-=prepaddlength;\n"
832 " int decoded_length=0;\n"
833 " int starting_pos=p_buf.get_pos_bit();\n"
834 " if(sel_field!=-1){\n"
835 " switch(sel_field){\n", name
);
836 for (i
= 0; i
< sdef
->nElements
; i
++) {
837 src
= mputprintf(src
,
839 " decoded_length = %s().RAW_decode(%s_descr_, p_buf, limit, "
840 "top_bit_ord, no_err);\n"
841 " break;\n", (unsigned long) i
, sdef
->elements
[i
].name
,
842 sdef
->elements
[i
].typedescrname
);
844 src
= mputstr(src
, " default: break;\n"
846 " return decoded_length + p_buf.increase_pos_padd(p_td.raw->padding) + "
849 /* only generate this variable if it will be used */
850 for (i
= 0; i
< sdef
->nElements
; i
++) {
851 if ((tag_type
[i
] > 0)
852 && (sdef
->raw
.taglist
.list
+ tag_type
[i
] - 1)->nElements
) {
853 src
= mputstr(src
, " boolean already_failed = FALSE;\n");
858 /* precalculate what we know about the temporal variables*/
859 for (i
= 0; i
< sdef
->nElements
; i
++) {
860 if ((tag_type
[i
] > 0)
861 && (sdef
->raw
.taglist
.list
+ tag_type
[i
] - 1)->nElements
) {
862 rawAST_coding_taglist
* cur_choice
= sdef
->raw
.taglist
.list
+ tag_type
[i
] - 1;
864 for (j
= 0; j
< cur_choice
->nElements
; j
++) {
865 rawAST_coding_field_list
*fieldlist
= cur_choice
->fields
+ j
;
866 if (fieldlist
->start_pos
>= 0) {
868 boolean found
= FALSE
;
869 for (k
= 0; k
< nTemp_variables
; k
++) {
870 if (temp_variable_list
[k
].start_pos
== fieldlist
->start_pos
871 && !strcmp(temp_variable_list
[k
].typedescr
,
872 fieldlist
->fields
[fieldlist
->nElements
- 1].typedescr
)) {
873 temp_variable_list
[k
].use_counter
++;
874 fieldlist
->temporal_variable_index
= k
;
881 = (temporal_variable
*) Realloc(temp_variable_list
,
882 (nTemp_variables
+ 1) * sizeof(*temp_variable_list
));
883 temp_variable_list
[nTemp_variables
].type
884 = fieldlist
->fields
[fieldlist
->nElements
- 1].type
;
885 temp_variable_list
[nTemp_variables
].typedescr
886 = fieldlist
->fields
[fieldlist
->nElements
- 1].typedescr
;
887 temp_variable_list
[nTemp_variables
].start_pos
888 = fieldlist
->start_pos
;
889 temp_variable_list
[nTemp_variables
].use_counter
= 1;
890 temp_variable_list
[nTemp_variables
].decoded_for_element
892 fieldlist
->temporal_variable_index
= nTemp_variables
;
900 for (i
= 0; i
< nTemp_variables
; i
++) {
901 if (temp_variable_list
[i
].use_counter
> 1) {
902 src
= mputprintf(src
, " %s temporal_%lu;\n"
903 " int decoded_%lu_length;\n", temp_variable_list
[i
].type
,
904 (unsigned long) i
, (unsigned long) i
);
908 for (i
= 0; i
< sdef
->nElements
; i
++) { /* fields with tag */
909 if ((tag_type
[i
] > 0)
910 && (sdef
->raw
.taglist
.list
+ tag_type
[i
] - 1)->nElements
) {
911 rawAST_coding_taglist
* cur_choice
= sdef
->raw
.taglist
.list
914 src
= mputstr(src
, " already_failed = FALSE;\n");
915 /* first check the fields we can precode
916 * try to decode those key variables whose position we know
917 * this way we might be able to step over bad values faster
919 for (j
= 0; j
< cur_choice
->nElements
; j
++) {
920 rawAST_coding_field_list
*cur_field_list
= cur_choice
->fields
+ j
;
921 if (cur_field_list
->start_pos
>= 0) {
923 size_t variable_index
= cur_field_list
->temporal_variable_index
;
924 if (temp_variable_list
[variable_index
].decoded_for_element
== i
) continue;
925 src
= mputstr(src
, " if (!already_failed) {\n");
926 if (temp_variable_list
[variable_index
].use_counter
== 1) {
927 src
= mputprintf(src
, " %s temporal_%lu;\n"
928 " int decoded_%lu_length;\n",
929 temp_variable_list
[variable_index
].type
,
930 (unsigned long) variable_index
, (unsigned long) variable_index
);
932 if (temp_variable_list
[variable_index
].decoded_for_element
934 src
= mputprintf(src
,
935 " p_buf.set_pos_bit(starting_pos + %d);\n"
936 " decoded_%lu_length = temporal_%lu.RAW_decode("
937 "%s_descr_, p_buf, limit, top_bit_ord, TRUE);\n",
938 cur_field_list
->start_pos
, (unsigned long) variable_index
,
939 (unsigned long) variable_index
,
940 temp_variable_list
[variable_index
].typedescr
);
942 temp_variable_list
[variable_index
].decoded_for_element
= i
;
943 src
= mputprintf(src
, " if (decoded_%lu_length > 0) {\n"
944 " if (temporal_%lu == %s", (unsigned long) variable_index
,
945 (unsigned long) variable_index
, cur_field_list
->value
);
946 for (k
= j
+ 1; k
< cur_choice
->nElements
; k
++) {
947 if (cur_choice
->fields
[k
].temporal_variable_index
949 src
= mputprintf(src
, " || temporal_%lu == %s",
950 (unsigned long) variable_index
, cur_choice
->fields
[k
].value
);
953 src
= mputprintf(src
, ") {\n"
954 " p_buf.set_pos_bit(starting_pos);\n"
955 " decoded_length = %s().RAW_decode(%s_descr_, p_buf, "
956 "limit, top_bit_ord, TRUE);\n"
957 " if (decoded_length > 0) {\n", sdef
->elements
[i
].name
,
958 sdef
->elements
[i
].typedescrname
);
959 src
= mputstr(src
, " if (");
960 src
= genRawFieldChecker(src
, cur_choice
, TRUE
);
961 src
= mputstr(src
, ") {\n"
962 " return decoded_length + "
963 "p_buf.increase_pos_padd(p_td.raw->padding) + prepaddlength;\n"
964 " }else already_failed = TRUE;\n"
971 /* if there is one tag key whose position we don't know
972 * and we couldn't decide yet if the element can be decoded or not
973 * than we have to decode it.
974 * note that this is not actually a cycle because of the break
976 for (j
= 0; j
< cur_choice
->nElements
; j
++) {
977 if (cur_choice
->fields
[j
].start_pos
< 0) {
978 src
= mputprintf(src
, " if (already_failed) {\n"
979 " p_buf.set_pos_bit(starting_pos);\n"
980 " decoded_length = %s().RAW_decode(%s_descr_, p_buf, limit, "
981 "top_bit_ord, TRUE);\n"
982 " if (decoded_length > 0) {\n", sdef
->elements
[i
].name
,
983 sdef
->elements
[i
].typedescrname
);
984 src
= mputstr(src
, " if (");
985 src
= genRawFieldChecker(src
, cur_choice
, TRUE
);
986 src
= mputstr(src
, ") {\n"
987 " return decoded_length + "
988 "p_buf.increase_pos_padd(p_td.raw->padding) + prepaddlength;\n"
997 Free(temp_variable_list
);
998 for (i
= 0; i
< sdef
->nElements
; i
++) { /* fields with only variable tag */
999 if ((tag_type
[i
] < 0)
1000 && (sdef
->raw
.taglist
.list
- tag_type
[i
] - 1)->nElements
) {
1001 rawAST_coding_taglist
* cur_choice
= sdef
->raw
.taglist
.list
1003 src
= mputprintf(src
, " p_buf.set_pos_bit(starting_pos);\n"
1004 " decoded_length = %s().RAW_decode(%s_descr_, p_buf, limit, "
1005 "top_bit_ord, TRUE);\n"
1006 " if (decoded_length >= 0) {\n", sdef
->elements
[i
].name
,
1007 sdef
->elements
[i
].typedescrname
);
1008 src
= mputstr(src
, " if (");
1009 src
= genRawFieldChecker(src
, cur_choice
, TRUE
);
1010 src
= mputstr(src
, ") {\n"
1011 " return decoded_length + "
1012 "p_buf.increase_pos_padd(p_td.raw->padding) + prepaddlength;\n"
1017 for (i
= 0; i
< sdef
->nElements
; i
++) { /* fields without tag */
1019 src
= mputprintf(src
, " p_buf.set_pos_bit(starting_pos);\n"
1020 " decoded_length = %s().RAW_decode(%s_descr_, p_buf, limit, "
1021 "top_bit_ord, TRUE);\n"
1022 " if (decoded_length >= 0) {\n", sdef
->elements
[i
].name
,
1023 sdef
->elements
[i
].typedescrname
);
1024 src
= mputstr(src
, " return decoded_length + "
1025 "p_buf.increase_pos_padd(p_td.raw->padding) + prepaddlength;\n"
1029 src
= mputstr(src
, " }\n"
1034 src
= mputprintf(src
, "int %s::RAW_encode("
1035 "const TTCN_Typedescriptor_t&%s, RAW_enc_tree& myleaf) const\n"
1036 "{\n", name
, use_runtime_2
? " p_td" : "");
1037 if (use_runtime_2
) {
1038 src
= mputstr(src
, " if (err_descr) return RAW_encode_negtest(err_descr, p_td, myleaf);\n");
1040 src
= mputprintf(src
,
1041 " int encoded_length = 0;\n"
1042 " myleaf.isleaf = FALSE;\n"
1043 " myleaf.body.node.num_of_nodes = %lu;"
1044 " myleaf.body.node.nodes = init_nodes_of_enc_tree(%lu);\n"
1045 " memset(myleaf.body.node.nodes, 0, %lu * sizeof(RAW_enc_tree *));\n"
1046 " switch (union_selection) {\n", (unsigned long)sdef
->nElements
,
1047 (unsigned long)sdef
->nElements
, (unsigned long)sdef
->nElements
);
1048 for (i
= 0; i
< sdef
->nElements
; i
++) {
1049 int t_type
= tag_type
[i
] > 0 ? tag_type
[i
] : -tag_type
[i
];
1050 src
= mputprintf(src
, " case %s_%s:\n"
1051 " myleaf.body.node.nodes[%lu] = new RAW_enc_tree(TRUE, &myleaf, "
1052 "&myleaf.curr_pos, %lu, %s_descr_.raw);\n"
1053 " encoded_length = field_%s->RAW_encode(%s_descr_, "
1054 "*myleaf.body.node.nodes[%lu]);\n"
1055 " myleaf.body.node.nodes[%lu]->coding_descr = &%s_descr_;\n",
1056 selection_prefix
, sdef
->elements
[i
].name
, (unsigned long) i
,
1057 (unsigned long) i
, sdef
->elements
[i
].typedescrname
,
1058 sdef
->elements
[i
].name
, sdef
->elements
[i
].typedescrname
,
1059 (unsigned long) i
, (unsigned long) i
, sdef
->elements
[i
].typedescrname
);
1060 if (t_type
&& (sdef
->raw
.taglist
.list
+ t_type
- 1)->nElements
) {
1061 rawAST_coding_taglist
* cur_choice
= sdef
->raw
.taglist
.list
+ t_type
- 1;
1062 src
= mputstr(src
, " if (");
1063 src
= genRawFieldChecker(src
, cur_choice
, FALSE
);
1064 src
= mputstr(src
, ") {\n");
1065 src
= genRawTagChecker(src
, cur_choice
);
1066 src
= mputstr(src
, " }\n");
1068 src
= mputstr(src
, " break;\n");
1070 src
= mputstr(src
, " default:\n"
1071 " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND, "
1072 "\"Encoding an unbound value.\");\n"
1074 " return encoded_length;\n"
1076 if (use_runtime_2
) {
1077 def
= mputstr(def
, "int RAW_encode_negtest(const Erroneous_descriptor_t *, "
1078 "const TTCN_Typedescriptor_t&, RAW_enc_tree&) const;\n");
1079 src
= mputprintf(src
, "int %s::RAW_encode_negtest(const Erroneous_descriptor_t *p_err_descr, "
1080 "const TTCN_Typedescriptor_t& /*p_td*/, RAW_enc_tree& myleaf) const\n"
1082 " const Erroneous_values_t *err_vals = NULL;\n"
1083 " const Erroneous_descriptor_t *emb_descr = NULL;\n"
1084 " int encoded_length = 0;\n"
1085 " myleaf.isleaf = FALSE;\n"
1086 " myleaf.body.node.num_of_nodes = %lu;\n"
1087 " myleaf.body.node.nodes = init_nodes_of_enc_tree(%lu);\n"
1088 " memset(myleaf.body.node.nodes, 0, %lu * sizeof(RAW_enc_tree *));\n"
1089 " switch (union_selection) {\n", name
, (unsigned long)sdef
->nElements
,
1090 (unsigned long)sdef
->nElements
, (unsigned long)sdef
->nElements
);
1091 for (i
= 0; i
< sdef
->nElements
; i
++) {
1092 int t_type
= tag_type
[i
] > 0 ? tag_type
[i
] : -tag_type
[i
];
1093 src
= mputprintf(src
,
1095 selection_prefix
, sdef
->elements
[i
].name
);
1096 if (t_type
&& (sdef
->raw
.taglist
.list
+ t_type
- 1)->nElements
) {
1097 src
= mputstr(src
, " bool negtest_confl_tag = false;\n");
1099 src
= mputprintf(src
,
1100 " err_vals = p_err_descr->get_field_err_values(%d);\n"
1101 " emb_descr = p_err_descr->get_field_emb_descr(%d);\n"
1102 " if (err_vals && err_vals->value) {\n"
1103 " if (err_vals->value->raw) {\n"
1104 " myleaf.body.node.nodes[%lu] =\n"
1105 " new RAW_enc_tree(TRUE, &myleaf, &myleaf.curr_pos, %lu, "
1106 "err_vals->value->errval->get_descriptor()->raw);\n"
1107 " encoded_length = err_vals->value->errval->RAW_encode_negtest_raw(*myleaf.body.node.nodes[%lu]);\n"
1108 " myleaf.body.node.nodes[%lu]->coding_descr = err_vals->value->errval->get_descriptor();\n"
1110 " if (err_vals->value->errval) {\n"
1111 " if (err_vals->value->type_descr == NULL)\n"
1112 " TTCN_error(\"internal error: erroneous value typedescriptor missing\");\n"
1113 " myleaf.body.node.nodes[%lu] = new RAW_enc_tree(TRUE, &myleaf, &myleaf.curr_pos, %lu, err_vals->value->type_descr->raw);\n"
1114 " encoded_length = err_vals->value->errval->RAW_encode(*err_vals->value->type_descr, *myleaf.body.node.nodes[%lu]);\n"
1115 " myleaf.body.node.nodes[%lu]->coding_descr = err_vals->value->type_descr;\n"
1119 (unsigned long)i
, (unsigned long)i
,
1120 (unsigned long)i
, (unsigned long)i
, (unsigned long)i
,
1121 (unsigned long)i
, (unsigned long)i
, (unsigned long)i
);
1122 if (t_type
&& (sdef
->raw
.taglist
.list
+ t_type
- 1)->nElements
) {
1124 src
= mputprintf(src
, " negtest_confl_tag = true;\n");
1126 src
= mputprintf(src
,
1128 " myleaf.body.node.nodes[%lu] = new RAW_enc_tree(TRUE, "
1129 "&myleaf, &myleaf.curr_pos, %lu, %s_descr_.raw);\n"
1130 " if (emb_descr) {\n",
1131 (unsigned long)i
, (unsigned long)i
, sdef
->elements
[i
].typedescrname
);
1132 if (t_type
&& (sdef
->raw
.taglist
.list
+ t_type
- 1)->nElements
) {
1134 src
= mputprintf(src
, " negtest_confl_tag = true;\n");
1136 src
= mputprintf(src
,
1137 " encoded_length = field_%s->RAW_encode_negtest(emb_descr, %s_descr_, *myleaf.body.node.nodes[%lu]);\n"
1138 " } else encoded_length = field_%s->RAW_encode(%s_descr_, *myleaf.body.node.nodes[%lu]);\n"
1139 " myleaf.body.node.nodes[%lu]->coding_descr = &%s_descr_;\n"
1141 sdef
->elements
[i
].name
, sdef
->elements
[i
].typedescrname
,
1142 (unsigned long)i
, sdef
->elements
[i
].name
,
1143 sdef
->elements
[i
].typedescrname
, (unsigned long)i
, (unsigned long)i
,
1144 sdef
->elements
[i
].typedescrname
);
1145 if (t_type
&& (sdef
->raw
.taglist
.list
+ t_type
- 1)->nElements
) {
1146 rawAST_coding_taglist
*cur_choice
= sdef
->raw
.taglist
.list
+ t_type
- 1;
1147 src
= mputprintf(src
,
1148 " if (negtest_confl_tag) {\n"
1149 " TTCN_EncDec_ErrorContext e_c;\n"
1150 " e_c.set_msg(\"Field '%s': \");\n"
1151 " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_NEGTEST_CONFL,\n"
1152 " \"Conflicting negative testing attributes, TAG attribute "
1153 "will be ignored\");\n"
1155 " if (!negtest_confl_tag && (", sdef
->elements
[i
].name
);
1156 src
= genRawFieldChecker(src
, cur_choice
, FALSE
);
1157 src
= mputstr(src
, ")) {\n");
1158 src
= genRawTagChecker(src
, cur_choice
);
1159 src
= mputstr(src
, " }\n");
1161 src
= mputstr(src
, " break; }\n");
1163 src
= mputstr(src
, " default:\n"
1164 " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND, "
1165 "\"Encoding an unbound value.\");\n"
1167 " return encoded_length;\n"
1171 } /* if raw_needed */
1174 src
= mputprintf(src
, "int %s::TEXT_encode("
1175 "const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf) const\n"
1177 if (use_runtime_2
) {
1178 src
= mputstr(src
, " if (err_descr) return TEXT_encode_negtest(err_descr, p_td, p_buf);\n");
1180 src
= mputstr(src
, " int encoded_length=0;\n"
1181 " if (p_td.text->begin_encode) {\n"
1182 " p_buf.put_cs(*p_td.text->begin_encode);\n"
1183 " encoded_length += p_td.text->begin_encode->lengthof();\n"
1185 " switch(union_selection){\n");
1186 for (i
= 0; i
< sdef
->nElements
; i
++) {
1187 src
= mputprintf(src
, " case %s_%s:\n"
1188 " encoded_length += field_%s->TEXT_encode(%s_descr_,p_buf);\n"
1189 " break;\n", selection_prefix
, sdef
->elements
[i
].name
,
1190 sdef
->elements
[i
].name
, sdef
->elements
[i
].typedescrname
);
1192 src
= mputstr(src
, " default:\n"
1193 " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND, "
1194 "\"Encoding an unbound value.\");\n"
1197 " if (p_td.text->end_encode) {\n"
1198 " p_buf.put_cs(*p_td.text->end_encode);\n"
1199 " encoded_length += p_td.text->end_encode->lengthof();\n"
1201 " return encoded_length;\n"
1203 if (use_runtime_2
) {/*TEXT_encde_negtest()*/
1205 "int TEXT_encode_negtest(const Erroneous_descriptor_t* p_err_descr, const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf) const;\n");
1206 src
= mputprintf(src
, "int %s::TEXT_encode_negtest("
1207 "const Erroneous_descriptor_t* p_err_descr, const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf) const\n"
1209 " int encoded_length=0;\n"
1210 " const Erroneous_values_t* err_vals = NULL;\n"
1211 " const Erroneous_descriptor_t* emb_descr = NULL;\n"
1212 " if (p_td.text->begin_encode) {\n"
1213 " p_buf.put_cs(*p_td.text->begin_encode);\n"
1214 " encoded_length += p_td.text->begin_encode->lengthof();\n"
1216 " switch(union_selection){\n", name
);
1217 for (i
= 0; i
< sdef
->nElements
; i
++) {
1218 src
= mputprintf(src
, " case %s_%s:\n"
1219 " err_vals = p_err_descr->get_field_err_values(%d);\n"
1220 " emb_descr = p_err_descr->get_field_emb_descr(%d);\n"
1221 " if (err_vals && err_vals->value){\n"
1222 " if (err_vals->value->errval) {\n"
1223 " if(err_vals->value->raw){\n"
1224 " encoded_length += err_vals->value->errval->encode_raw(p_buf);\n"
1226 " if (err_vals->value->type_descr==NULL) TTCN_error(\"internal error: erroneous value typedescriptor missing\");\n"
1227 " encoded_length += err_vals->value->errval->TEXT_encode(*err_vals->value->type_descr,p_buf);\n"
1231 " if (emb_descr) encoded_length += field_%s->TEXT_encode_negtest(emb_descr,%s_descr_,p_buf);\n"
1232 " else field_%s->TEXT_encode(%s_descr_,p_buf);\n"
1234 " break;\n", selection_prefix
, sdef
->elements
[i
].name
,(int)i
,(int)i
,
1235 sdef
->elements
[i
].name
, sdef
->elements
[i
].typedescrname
, sdef
->elements
[i
].name
, sdef
->elements
[i
].typedescrname
);
1237 src
= mputstr(src
, " default:\n"
1238 " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND, "
1239 "\"Encoding an unbound value.\");\n"
1242 " if (p_td.text->end_encode) {\n"
1243 " p_buf.put_cs(*p_td.text->end_encode);\n"
1244 " encoded_length += p_td.text->end_encode->lengthof();\n"
1246 " return encoded_length;\n"
1250 src
= mputprintf(src
, "int %s::TEXT_decode("
1251 "const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf, "
1252 "Limit_Token_List& limit, boolean no_err, boolean)\n"
1254 " int decoded_length = 0;\n"
1255 " if(p_td.text->begin_decode){\n"
1256 " int tl = p_td.text->begin_decode->match_begin(p_buf);\n"
1258 " decoded_length += tl;\n"
1259 " p_buf.increase_pos(tl);\n"
1261 " if (no_err) return -1;\n"
1262 " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_TOKEN_ERR, "
1263 "\"The specified token '%%s' not found for '%%s': \", "
1264 "(const char*)(*p_td.text->begin_decode), p_td.name);\n"
1268 " if (p_buf.get_read_len() < 1 && no_err) return -1;\n"
1271 " boolean found = FALSE;\n"
1272 " if (p_td.text->end_decode) {\n"
1273 " limit.add_token(p_td.text->end_decode);\n"
1275 " }\n", name
, sdef
->nElements
> 1 ? " size_t pos = p_buf.get_pos();\n" : "");
1276 if (sdef
->nElements
> 0) {
1277 src
= mputprintf(src
,
1278 " int str_len = %s().TEXT_decode(%s_descr_, p_buf, limit, true);\n"
1279 " if (str_len >= 0) found = TRUE;\n", sdef
->elements
[0].name
,
1280 sdef
->elements
[0].typedescrname
);
1282 for (i
= 1; i
< sdef
->nElements
; i
++) {
1283 src
= mputprintf(src
, " if (!found) {\n"
1284 " p_buf.set_pos(pos);\n"
1285 " str_len = %s().TEXT_decode(%s_descr_, p_buf, limit, true);\n"
1286 " if (str_len >= 0) found = TRUE;\n"
1287 " }\n", sdef
->elements
[i
].name
, sdef
->elements
[i
].typedescrname
);
1289 src
= mputstr(src
, " limit.remove_tokens(ml);\n"
1291 " decoded_length += str_len;\n"
1292 " if (p_td.text->end_decode) {\n"
1293 " int tl = p_td.text->end_decode->match_begin(p_buf);\n"
1295 " decoded_length += tl;\n"
1296 " p_buf.increase_pos(tl);\n"
1298 " if (no_err) return -1;\n"
1299 " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_TOKEN_ERR, "
1300 "\"The specified token '%s' not found for '%s': \", "
1301 "(const char*)(*p_td.text->end_decode), p_td.name);\n"
1305 " if (no_err) return -1;\n"
1306 " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_TOKEN_ERR, "
1307 "\"No union member found for '%s': \", p_td.name);\n"
1310 " return decoded_length;\n"
1314 if (xer_needed
) { /* XERSTUFF encoder functions for union */
1316 "char **collect_ns(const XERdescriptor_t& p_td, size_t& num, bool& def_ns) const;\n");
1319 "boolean %s::can_start(const char *name, const char *uri,"
1320 " const XERdescriptor_t& xd, unsigned int flavor) {\n"
1321 " boolean exer = is_exer(flavor);\n"
1322 " if (!exer || (!(xd.xer_bits & UNTAGGED) && !(flavor & (USE_NIL|(exer ? XER_LIST : XER_RECOF))))) "
1323 /* If the union has no own tag, there is nothing to check. */
1324 "return check_name(name, xd, exer)" /* if false, return immediately */
1325 " && (!exer || (flavor & USE_TYPE_ATTR) || check_namespace(uri, xd));\n"
1326 /* else check the ns, unless Basic XER (which has no namespaces, ever)
1327 * or USE_TYPE (where we only have a name from the type id attribute) */
1330 src
= mputstr(src
, " flavor &= ~XER_RECOF;\n");
1332 /* An untagged union can start with the start tag of any alternative */
1333 for (i
= 0; i
< sdef
->nElements
; i
++) {
1335 " if (%s::can_start(name, uri, %s_xer_, flavor)) return true;\n"
1336 , sdef
->elements
[i
].type
, sdef
->elements
[i
].typegen
1339 src
= mputstr(src
, " return false;\n}\n\n");
1341 src
= mputprintf(src
,
1342 "char ** %s::collect_ns(const XERdescriptor_t& p_td, size_t& num, bool& def_ns) const {\n"
1343 " size_t num_collected;\n"
1344 " char **collected_ns = Base_Type::collect_ns(p_td, num_collected, def_ns);\n"
1345 /* Two-level new memory allocated */
1347 " size_t num_new;\n"
1348 " boolean need_type = FALSE;\n"
1350 " bool def_ns_1 = false;\n"
1351 " switch (union_selection) {\n"
1354 for (i
= 0; i
< sdef
->nElements
; i
++) {
1355 src
= mputprintf(src
,
1357 " new_ns = field_%s->collect_ns(%s_xer_, num_new, def_ns_1);\n"
1358 " def_ns = def_ns || def_ns_1;\n" /* alas, no ||= */
1359 " merge_ns(collected_ns, num_collected, new_ns, num_new);\n"
1360 /* merge_ns() deallocated new_ns and duplicated strings,
1361 * copied the new ones into the expanded new_ns */
1362 , selection_prefix
, sdef
->elements
[i
].name
1363 , sdef
->elements
[i
].name
1364 , sdef
->elements
[i
].typegen
1366 /* Type id attribute not needed for the first field in case of USE-TYPE */
1367 if (sdef
->xerUseUnion
|| i
> 0) src
= mputprintf(src
,
1368 " need_type = (%s_xer_.namelens[1] > 2);\n"
1369 , sdef
->elements
[i
].typegen
);
1370 src
= mputstr(src
, " break;\n");
1374 " default: break;\n"
1376 " if ((p_td.xer_bits & USE_TYPE_ATTR) && !(p_td.xer_bits & XER_ATTRIBUTE) && need_type) {\n"
1377 /* control ns for type attribute */
1378 " collected_ns = (char**)Realloc(collected_ns, sizeof(char*) * ++num_collected);\n"
1379 " const namespace_t *c_ns = p_td.my_module->get_controlns();\n"
1380 " collected_ns[num_collected-1] = mprintf(\" xmlns:%s='%s'\", c_ns->px, c_ns->ns);\n"
1384 /* Probably a TC_Error thrown from field_%s->collect_ns() if e.g.
1385 * encoding an unbound value. */
1386 " while (num_collected > 0) Free(collected_ns[--num_collected]);\n"
1387 " Free(collected_ns);\n"
1390 " num = num_collected;\n"
1391 " return collected_ns;\n"
1395 src
= mputprintf(src
, /* XERSTUFF XER_encode for union */
1396 "int %s::XER_encode(const XERdescriptor_t& p_td, TTCN_Buffer& p_buf, "
1397 "unsigned int p_flavor, int p_indent, embed_values_enc_struct_t*) const\n"
1400 " if (%s==union_selection) {\n"
1401 " TTCN_error(\"Attempt to XER-encode an unbound union value.\");\n"
1404 " TTCN_EncDec_ErrorContext ec_0(\"Alternative '\");\n"
1405 " TTCN_EncDec_ErrorContext ec_1;\n"
1406 " int encoded_length=(int)p_buf.get_len();\n"
1408 , (use_runtime_2
? " if (err_descr) return XER_encode_negtest"
1409 "(err_descr, p_td, p_buf, p_flavor, p_indent, 0);\n" : "")
1413 if (sdef
->xerUseTypeAttr
) {
1415 " const boolean e_xer = is_exer(p_flavor);\n"
1416 " char *type_atr = NULL;\n"
1417 " if (e_xer && (p_td.xer_bits & USE_TYPE_ATTR)) {\n"
1418 " char *type_name = 0;\n"
1419 " const namespace_t *control_ns;\n"
1420 " switch (union_selection) {\n");
1421 /* In case of USE-TYPE the first field won't need the type attribute */
1422 int start_at
= sdef
->xerUseUnion
? 0 : 1;
1423 for (i
= start_at
; i
< sdef
->nElements
; i
++) {
1424 src
= mputprintf(src
,
1426 " if (%s_xer_.my_module != 0 && %s_xer_.ns_index != -1 &&\n"
1427 " %s_xer_.namelens[1] > 2) {\n"
1428 /* add the namespace prefix to the type attribute (if the name is not empty) */
1429 " const namespace_t *my_ns = %s_xer_.my_module->get_ns(%s_xer_.ns_index);\n"
1430 " if (my_ns->px[0] != 0) {\n"
1431 " type_name = mprintf(\"%%s:\", my_ns->px);\n"
1434 " type_name = mputstrn(type_name, %s_xer_.names[1], %s_xer_.namelens[1] - 2);\n"
1436 , selection_prefix
, sdef
->elements
[i
].name
1437 , sdef
->elements
[i
].typegen
, sdef
->elements
[i
].typegen
1438 , sdef
->elements
[i
].typegen
, sdef
->elements
[i
].typegen
1439 , sdef
->elements
[i
].typegen
, sdef
->elements
[i
].typegen
1440 , sdef
->elements
[i
].typegen
1441 , i
< sdef
->nElements
- 1 ? "goto write_atr;" : "" /* no break */
1444 src
= mputprintf(src
,
1445 "%s" /* label only if more than two elements total */
1446 " if (mstrlen(type_name) > 0) {\n" /* 38.3.8, no atr if NAME AS "" */
1447 " control_ns = p_td.my_module->get_controlns();\n"
1448 " type_atr = mcopystr(\" \");\n"
1449 " type_atr = mputstr(type_atr, control_ns->px);\n"
1450 " type_atr = mputstr(type_atr, \":type='\");\n"
1451 " type_atr = mputstr(type_atr, type_name);\n"
1452 " type_atr = mputc (type_atr, '\\'');\n"
1453 " Free(type_name);\n"
1456 " default: break;\n"
1458 " p_flavor &= ~XER_RECOF;\n"
1459 " }\n" /* if e_xer */
1460 , (sdef
->nElements
> start_at
+ 1 ? "write_atr:\n" : "")
1464 } /* if UseTypeAttr */
1465 src
= mputprintf(src
,
1466 " unsigned int flavor_1 = p_flavor;\n"
1467 " if (is_exer(p_flavor)) flavor_1 &= ~XER_RECOF;\n"
1468 " bool omit_tag = begin_xml(p_td, p_buf, flavor_1, p_indent, false, "
1469 "(collector_fn)&%s::collect_ns%s);\n"
1471 , sdef
->xerUseTypeAttr
? ", type_atr" : "");
1472 src
= mputprintf(src
,
1473 " unsigned int flavor_0 = (p_flavor & XER_MASK)%s;\n"
1474 " switch (union_selection) {\n"
1475 , sdef
->xerUseTypeAttr
? " | USE_TYPE_ATTR" : "");
1476 for (i
= 0; i
< sdef
->nElements
; i
++) {
1477 src
= mputprintf(src
, " case %s_%s:\n"
1478 " ec_1.set_msg(\"%s': \");\n"
1479 " field_%s->XER_encode(%s_xer_, p_buf, flavor_0, "
1480 "p_indent + (!p_indent || !omit_tag), 0);\n"
1482 selection_prefix
, sdef
->elements
[i
].name
,
1483 sdef
->elements
[i
].dispname
,
1484 sdef
->elements
[i
].name
, sdef
->elements
[i
].typegen
);
1486 src
= mputprintf(src
, " case %s:\n"
1487 " (void)flavor_0;\n" /* warning reduction for empty union */
1491 if (sdef
->xerUseTypeAttr
) {
1492 src
= mputstr(src
, " if (p_buf.get_data()[p_buf.get_len()-1] != '\\n') flavor_1 |= SIMPLE_TYPE;\n");
1495 " end_xml(p_td, p_buf, flavor_1, p_indent, 0);\n"
1496 " return (int)p_buf.get_len() - encoded_length;\n"
1499 if (use_runtime_2
) {
1501 "int XER_encode_negtest(const Erroneous_descriptor_t* p_err_descr, "
1502 "const XERdescriptor_t& p_td, TTCN_Buffer& p_buf, "
1503 "unsigned int p_flavor, int p_indent, embed_values_enc_struct_t*) const;\n");
1504 src
= mputprintf(src
, /* XERSTUFF XER_encode for union */
1505 "int %s::XER_encode_negtest(const Erroneous_descriptor_t* p_err_descr, "
1506 "const XERdescriptor_t& p_td, TTCN_Buffer& p_buf, "
1507 "unsigned int p_flavor, int p_indent, embed_values_enc_struct_t*) const\n"
1509 " if (%s==union_selection) {\n"
1510 " TTCN_error(\"Attempt to XER-encode an unbound union value.\");\n"
1513 " TTCN_EncDec_ErrorContext ec_0(\"Alternative '\");\n"
1514 " TTCN_EncDec_ErrorContext ec_1;\n"
1515 " int encoded_length=(int)p_buf.get_len();\n"
1519 if (sdef
->xerUseTypeAttr
) {
1521 " const boolean e_xer = is_exer(p_flavor);\n"
1522 " char *type_atr = NULL;\n"
1523 " if (e_xer && (p_td.xer_bits & USE_TYPE_ATTR)) {\n"
1524 " char *type_name = 0;\n"
1525 " const namespace_t *control_ns;\n"
1526 " switch (union_selection) {\n");
1527 int start_at
= sdef
->xerUseUnion
? 0 : 1;
1528 for (i
= start_at
; i
< sdef
->nElements
; i
++) {
1529 src
= mputprintf(src
,
1531 " if (%s_xer_.my_module != 0 && %s_xer_.ns_index != -1 &&\n"
1532 " %s_xer_.namelens[1] > 2) {\n"
1533 /* add the namespace prefix to the type attribute (if the name is not empty) */
1534 " const namespace_t *my_ns = %s_xer_.my_module->get_ns(%s_xer_.ns_index);\n"
1535 " if (my_ns->px[0] != 0) {\n"
1536 " type_name = mprintf(\"%%s:\", my_ns->px);\n"
1539 " type_name = mputstrn(type_name, %s_xer_.names[1], %s_xer_.namelens[1] - 2);\n"
1541 , selection_prefix
, sdef
->elements
[i
].name
1542 , sdef
->elements
[i
].typegen
, sdef
->elements
[i
].typegen
1543 , sdef
->elements
[i
].typegen
, sdef
->elements
[i
].typegen
1544 , sdef
->elements
[i
].typegen
, sdef
->elements
[i
].typegen
1545 , sdef
->elements
[i
].typegen
1546 , i
< sdef
->nElements
- 1 ? "goto write_atr;" : "" /* no break */
1549 src
= mputprintf(src
,
1550 "%s" /* label only if more than two elements total */
1551 " if (mstrlen(type_name) > 0) {\n" /* 38.3.8, no atr if NAME AS "" */
1552 " control_ns = p_td.my_module->get_controlns();\n"
1553 " type_atr = mcopystr(\" \");\n"
1554 " type_atr = mputstr(type_atr, control_ns->px);\n"
1555 " type_atr = mputstr(type_atr, \":type='\");\n"
1556 " type_atr = mputstr(type_atr, type_name);\n"
1557 " type_atr = mputc (type_atr, '\\'');\n"
1558 " Free(type_name);\n"
1561 " default: break;\n"
1563 " p_flavor &= ~XER_RECOF;\n"
1564 " }\n" /* if e_xer */
1565 , (sdef
->nElements
> start_at
+ 1 ? "write_atr:\n" : "")
1567 } /* if UseTypeAttr */
1569 src
= mputprintf(src
,
1570 " bool omit_tag = begin_xml(p_td, p_buf, p_flavor, p_indent, false, "
1571 "(collector_fn)&%s::collect_ns%s);\n"
1573 , sdef
->xerUseTypeAttr
? ", type_atr" : "");
1574 /* begin_xml will Free type_atr */
1575 src
= mputprintf(src
,
1576 " unsigned int flavor_0 = (p_flavor & XER_MASK)%s;\n"
1577 " const Erroneous_values_t* err_vals = NULL;\n"
1578 " const Erroneous_descriptor_t* emb_descr = NULL;\n"
1579 " switch (union_selection) {\n"
1580 , sdef
->xerUseTypeAttr
? " | USE_TYPE_ATTR" : "");
1581 for (i
= 0; i
< sdef
->nElements
; i
++) {
1582 src
= mputprintf(src
, " case %s_%s:\n"
1583 " err_vals = p_err_descr->get_field_err_values(%lu);\n"
1584 " emb_descr = p_err_descr->get_field_emb_descr(%lu);\n"
1585 " if (err_vals && err_vals->value) {\n"
1586 " if (err_vals->value->errval) {\n"
1587 " ec_1.set_msg(\"%s'(erroneous value): \");\n"
1588 " if (err_vals->value->raw) {\n"
1589 " err_vals->value->errval->encode_raw(p_buf);\n"
1591 " if (err_vals->value->type_descr==NULL) TTCN_error"
1592 "(\"internal error: erroneous value typedescriptor missing\");\n"
1593 " else err_vals->value->errval->XER_encode("
1594 "*err_vals->value->type_descr->xer, p_buf, flavor_0, "
1595 "p_indent + (!p_indent || !omit_tag), 0);\n"
1599 " ec_1.set_msg(\"%s': \");\n"
1600 " if (emb_descr) field_%s->XER_encode_negtest(emb_descr, "
1601 "%s_xer_, p_buf, flavor_0, p_indent + (!p_indent || !omit_tag), 0);\n"
1602 " else field_%s->XER_encode(%s_xer_, p_buf, flavor_0, "
1603 "p_indent + (!p_indent || !omit_tag), 0);\n"
1606 selection_prefix
, sdef
->elements
[i
].name
, /* case label */
1607 (unsigned long)i
, (unsigned long)i
,
1608 sdef
->elements
[i
].dispname
, /* set_msg (erroneous) */
1609 sdef
->elements
[i
].dispname
, /* set_msg */
1610 sdef
->elements
[i
].name
, sdef
->elements
[i
].typegen
,
1611 sdef
->elements
[i
].name
, sdef
->elements
[i
].typegen
/* field_%s, %s_descr */
1614 src
= mputprintf(src
, " case %s:\n"
1615 " (void)flavor_0;\n" /* warning reduction for empty union */
1618 " end_xml(p_td, p_buf, p_flavor, p_indent, 0);\n"
1619 " return (int)p_buf.get_len() - encoded_length;\n"
1625 src
= mputprintf(src
, "// %s has%s%s%s%s%s%s%s%s%s\n"
1626 "// written by %s in " __FILE__
" at %d\n"
1628 , (sdef
->xerUntagged
? " UNTAGGED" : "")
1629 , (sdef
->xerUntaggedOne
? "1" : "")
1630 , (sdef
->xerUseNilPossible
? " USE_NIL?" : "")
1631 , (sdef
->xerUseOrderPossible
? " USE_ORDER?" : "")
1632 , (sdef
->xerUseQName
? " USE_QNAME" : "")
1633 , (sdef
->xerUseTypeAttr
? " USE_TYPE_ATTR" : "")
1634 , (sdef
->xerUseUnion
? " USE-UNION" : "")
1635 , (sdef
->xerHasNamespaces
? " namespace" : "")
1636 , (sdef
->xerEmbedValuesPossible
? " EMBED?" : "")
1637 , __FUNCTION__
, __LINE__
1640 src
= mputprintf(src
, /* XERSTUFF decoder functions for union */
1641 "int %s::XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& p_reader,"
1642 " unsigned int p_flavor, unsigned int p_flavor2, embed_values_dec_struct_t*)\n"
1644 " int e_xer = is_exer(p_flavor);\n"
1645 " int type = 0;\n" /* None */
1646 " int rd_ok=1, xml_depth=-1;\n"
1648 " int xerbits = p_td.xer_bits;\n"
1649 " if (p_flavor & XER_TOPLEVEL) xerbits &= ~UNTAGGED;\n"
1650 " if (xerbits & USE_TYPE_ATTR) p_flavor &= ~XER_RECOF;\n"
1651 " boolean own_tag = !(e_xer && ((xerbits & (ANY_ELEMENT | UNTAGGED)) "
1652 "|| (p_flavor & (USE_NIL|(e_xer ? XER_LIST : XER_RECOF)))));\n"
1653 " if ((e_xer || !is_record_of(p_flavor)) && own_tag)\n"
1654 /* Loop until the start tag */
1655 " %sfor (rd_ok = p_reader.Ok(); rd_ok == 1; rd_ok = p_reader.Read()) {\n"
1656 " type = p_reader.NodeType();\n"
1657 " if (type == XML_READER_TYPE_ELEMENT) {\n"
1658 " verify_name(p_reader, p_td, e_xer);\n"
1659 " xml_depth = p_reader.Depth();\n"
1661 , sdef
->xerUseTypeAttr
? " char * typeatr = 0;\n" : ""
1662 , sdef
->xerUseUnion
? " boolean attribute = (p_td.xer_bits & XER_ATTRIBUTE) ? true : false;\n" : ""
1663 , sdef
->xerUseUnion
? "if (!attribute) " : ""
1665 if (sdef
->xerUseTypeAttr
) {
1666 src
= mputprintf(src
,
1667 " int other_attributes = 0;\n"
1669 " for (rd_ok = p_reader.MoveToFirstAttribute(); rd_ok == 1;"
1670 " rd_ok = p_reader.MoveToNextAttribute()) {\n"
1671 " if (p_reader.IsNamespaceDecl()) continue;\n"
1672 " const char *attr_name = (const char*)p_reader.Name();\n"
1673 " if (!strcmp(attr_name, \"%s:type\"))\n"
1675 " typeatr = mcopystr((const char*)p_reader.Value());\n"
1677 " else ++other_attributes;\n"
1679 " rd_ok = p_reader.MoveToElement() | 1;\n"
1680 , sdef
->control_ns_prefix
);
1681 if (!sdef
->xerUseUnion
) {
1682 /* USE-TYPE: No type attribute means the first alternative */
1683 src
= mputprintf(src
,
1684 " if (typeatr == NULL) {\n"
1685 " typeatr = mcopystrn(%s_xer_.names[1], %s_xer_.namelens[1] - 2);\n"
1687 , sdef
->elements
[0].typegen
1688 , sdef
->elements
[0].typegen
);
1691 " }\n" /* if exer */);
1694 src
= mputprintf(src
,
1695 " if (!(e_xer && (p_td.xer_bits & USE_TYPE_ATTR)%s)\n"
1696 " && !p_reader.IsEmptyElement()) rd_ok = p_reader.Read();\n"
1700 " unsigned int flavor_1 = (p_flavor & XER_MASK);\n" /* also, not toplevel */
1701 /* Loop until the content. Normally an element, unless UNTAGGED
1702 * USE-UNION or some other shenanigans. */
1703 " %s%sfor (rd_ok = p_reader.Ok(); rd_ok == 1; rd_ok = p_reader.Read()) {\n"
1704 " type = p_reader.NodeType();\n"
1705 " %sif (type == XML_READER_TYPE_ELEMENT) break;\n"
1706 " else if (type == XML_READER_TYPE_END_ELEMENT) break;\n"
1709 " TTCN_EncDec_ErrorContext ec_1(\"Alternative '\");\n"
1710 " TTCN_EncDec_ErrorContext ec_2;\n"
1711 " const char *elem_name;\n"
1712 " const char *ns_uri = 0;\n"
1713 , sdef
->xerUseTypeAttr
? " && other_attributes > 0" : ""
1714 , sdef
->xerUseTypeAttr
? "if (!e_xer) " : ""
1715 , sdef
->xerUseUnion
? "if (!attribute) " : ""
1716 , sdef
->xerUseTypeAttr
?
1717 "if (e_xer) { if (type == XML_READER_TYPE_TEXT) break; }\n"
1721 if (sdef
->xerUseTypeAttr
) {
1723 " if (e_xer) {\n" /* USE-TYPE => no XML element, use typeatr */
1724 " char *token_1 = strtok(typeatr, \":\");\n" /* extract the namespace (if any) */
1725 " char *token_2 = strtok(NULL, \":\");\n"
1726 " if (token_2) {\n" /* namespace found */
1727 " elem_name = token_2;\n"
1728 " ns_uri = get_ns_uri_from_prefix(token_1, p_td);\n"
1730 " else {\n" /* no namespace */
1731 " elem_name = token_1;\n"
1733 " flavor_1 |= USE_TYPE_ATTR;\n"
1735 " else" /* no newline, gobbles up the next {} */);
1739 " elem_name = (const char*)p_reader.LocalName();\n"
1740 " ns_uri = (const char*)p_reader.NamespaceUri();\n"
1743 if (sdef
->xerUseUnion
) {
1745 " int matched = -1;\n"
1746 " if (typeatr == NULL) flavor_1 |= EXIT_ON_ERROR;\n"
1748 /* TODO unify the two alternatives */
1749 for (i
= 0; i
< sdef
->nElements
; i
++) {
1750 src
= mputprintf(src
,
1751 /* If decoding EXER, there is no tag to apply check_name
1754 " if ((e_xer && (typeatr == NULL || !(p_td.xer_bits & USE_TYPE_ATTR))) "
1755 "|| can_start(elem_name, ns_uri, %s_xer_, flavor_1)) {\n"
1756 " ec_2.set_msg(\"%s': \");\n"
1757 " if (%s==union_selection) {\n"
1759 " %s().XER_decode(%s_xer_, p_reader, flavor_1, p_flavor2, 0);\n"
1761 " if (field_%s->is_bound()) break; else clean_up();\n"
1763 sdef
->elements
[i
].typegen
,
1764 sdef
->elements
[i
].dispname
,
1765 unbound_value
, (int)i
,
1766 sdef
->elements
[i
].name
, sdef
->elements
[i
].typegen
,
1767 sdef
->elements
[i
].name
);
1770 " if (typeatr == NULL) {\n"
1771 /* No type attribute found and none of the fields managed to decode the value (USE-UNION only) */
1772 " ec_1.set_msg(\" \");\n"
1773 " ec_2.set_msg(\" \");\n"
1774 " const char* value = (const char*)p_reader.Value();\n"
1775 " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_INVAL_MSG,\n"
1776 " \"'%s' could not be decoded by any of the union's fields.\", value);\n"
1777 " } else if (matched >= 0) {\n"
1778 /* Alternative found, but it couldn't be decoded */
1779 " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_INVAL_MSG,\n"
1780 " \"Failed to decode field.\");\n"
1782 /* Type attribute found, but it didn't match any of the fields */
1783 " ec_1.set_msg(\" \");\n"
1784 " ec_2.set_msg(\" \");\n"
1785 " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_INVAL_MSG,\n"
1786 " \"'%s' does not match any alternative.\", elem_name);\n"
1788 " if (xml_depth >= 0) for (; rd_ok == 1 "
1789 "&& p_reader.Depth() > xml_depth; rd_ok = p_reader.Read()) ;\n"
1791 " }\n"); /* for ever */
1793 else /* not USE-UNION */
1795 if (sdef
->exerMaybeEmptyIndex
>= 0) {
1796 /* There is a field which can be empty XML. Add code to detect this
1797 * and jump to the appropriate field which can decode "nothing". */
1799 " if (type!=XML_READER_TYPE_ELEMENT || "
1800 "(own_tag && p_reader.IsEmptyElement())) goto empty_xml;\n");
1801 /* If the choice itself is untagged, then an empty element belongs to
1802 * one of the fields and does not mean that the choice is empty */
1804 /* FIXME some hashing should be implemented */
1805 /* The field which can be empty should be checked last, otherwise we create an infinity loop with memory bomb.
1806 * So move that field to the last elseif branch*/
1807 for (i
= 0; i
< sdef
->nElements
; i
++) {
1808 if(sdef
->exerMaybeEmptyIndex
!= i
){
1809 src
= mputprintf(src
,
1810 " %sif (%s::can_start(elem_name, ns_uri, %s_xer_, flavor_1) || (%s_xer_.xer_bits & ANY_ELEMENT)) {\n"
1811 " ec_2.set_msg(\"%s': \");\n"
1812 " if (e_xer && (%s_xer_.xer_bits & BLOCKED)) {\n"
1813 " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_INVAL_MSG,\n"
1814 " \"Attempting to decode blocked or abstract field.\");\n"
1816 " %s%s().XER_decode(%s_xer_, p_reader, flavor_1, p_flavor2, 0);\n"
1817 " if (!%s%s().is_bound()) {\n"
1818 " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_INVAL_MSG, \"Failed to decode field.\");\n"
1821 i
&& !(i
==1 && sdef
->exerMaybeEmptyIndex
==0) ? "else " : "", /* print "if(" if generate code for the first field or if the first field is the MaybeEmpty field and we generate the code for the second one*/
1822 sdef
->elements
[i
].type
, sdef
->elements
[i
].typegen
, sdef
->elements
[i
].typegen
,
1823 sdef
->elements
[i
].dispname
,
1824 sdef
->elements
[i
].typegen
,
1825 at_field
, sdef
->elements
[i
].name
, sdef
->elements
[i
].typegen
,
1826 at_field
, sdef
->elements
[i
].name
);
1829 if(sdef
->exerMaybeEmptyIndex
>=0 ){
1830 i
=sdef
->exerMaybeEmptyIndex
;
1831 src
= mputprintf(src
,
1832 " %sif ((e_xer && (type==XML_READER_TYPE_END_ELEMENT || !own_tag)) || %s::can_start(elem_name, ns_uri, %s_xer_, flavor_1) || (%s_xer_.xer_bits & ANY_ELEMENT)) {\n"
1833 "empty_xml: ec_2.set_msg(\"%s': \");\n"
1834 " if (e_xer && (%s_xer_.xer_bits & BLOCKED)) {\n"
1835 " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_INVAL_MSG,\n"
1836 " \"Attempting to decode blocked or abstract field.\");\n"
1838 " %s%s().XER_decode(%s_xer_, p_reader, flavor_1, p_flavor2, 0);\n"
1839 " if (!%s%s().is_bound()) {\n"
1840 " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_INVAL_MSG, \"Failed to decode field.\");\n"
1843 sdef
->nElements
>0 ? "else " : "",
1844 sdef
->elements
[i
].type
, sdef
->elements
[i
].typegen
, sdef
->elements
[i
].typegen
,
1845 sdef
->elements
[i
].dispname
,
1846 sdef
->elements
[i
].typegen
,
1847 at_field
, sdef
->elements
[i
].name
, sdef
->elements
[i
].typegen
,
1848 at_field
, sdef
->elements
[i
].name
);
1850 if (!sdef
->isOptional
) {
1853 " ec_1.set_msg(\" \");\n"
1854 " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_INVAL_MSG, "
1855 "\"'%s' does not match any alternative\", elem_name);\n"
1856 " if (xml_depth >= 0) for (; rd_ok == 1 "
1857 "&& p_reader.Depth() > xml_depth; rd_ok = p_reader.Read()) ;\n"
1863 src
= mputprintf(src
,
1864 " }\n" /* end if(rd_ok) */
1865 " if (%s(e_xer || !is_record_of(p_flavor)) && own_tag)\n"
1866 " for (; rd_ok == 1; rd_ok = p_reader.Read()) {\n"
1867 " type = p_reader.NodeType();\n"
1868 " if (type == XML_READER_TYPE_END_ELEMENT) {\n"
1869 " verify_end(p_reader, p_td, xml_depth, e_xer);\n"
1870 " rd_ok = p_reader.Read(); // one last time\n"
1876 "}\n\n", sdef
->xerUseUnion
? "!attribute && " : "",
1877 sdef
->xerUseTypeAttr
? " Free(typeatr);\n" : "");
1881 src
= mputprintf(src
,
1882 "int %s::JSON_encode(const TTCN_Typedescriptor_t&%s, JSON_Tokenizer& p_tok) const\n"
1883 "{\n", name
, use_runtime_2
? " p_td" : "");
1884 if (use_runtime_2
) {
1885 src
= mputstr(src
, " if (err_descr) return JSON_encode_negtest(err_descr, p_td, p_tok);\n");
1887 if (!sdef
->jsonAsValue
) {
1888 src
= mputstr(src
, " int enc_len = p_tok.put_next_token(JSON_TOKEN_OBJECT_START, NULL);\n\n");
1890 src
= mputstr(src
, " int enc_len = 0;\n\n");
1892 src
= mputstr(src
, " switch(union_selection) {\n");
1894 for (i
= 0; i
< sdef
->nElements
; ++i
) {
1895 src
= mputprintf(src
, " case %s_%s:\n", selection_prefix
, sdef
->elements
[i
].name
);
1896 if (!sdef
->jsonAsValue
) {
1897 src
= mputprintf(src
, " enc_len += p_tok.put_next_token(JSON_TOKEN_NAME, \"%s\");\n"
1898 , sdef
->elements
[i
].jsonAlias
? sdef
->elements
[i
].jsonAlias
: sdef
->elements
[i
].dispname
);
1900 src
= mputprintf(src
,
1901 " enc_len += field_%s->JSON_encode(%s_descr_, p_tok);\n"
1903 , sdef
->elements
[i
].name
, sdef
->elements
[i
].typedescrname
);
1905 src
= mputprintf(src
,
1907 " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND, \n"
1908 " \"Encoding an unbound value of type %s.\");\n"
1912 if (!sdef
->jsonAsValue
) {
1913 src
= mputstr(src
, " enc_len += p_tok.put_next_token(JSON_TOKEN_OBJECT_END, NULL);\n");
1916 " return enc_len;\n"
1919 if (use_runtime_2
) {
1920 // JSON encode for negative testing
1922 "int JSON_encode_negtest(const Erroneous_descriptor_t*, "
1923 "const TTCN_Typedescriptor_t&, JSON_Tokenizer&) const;\n");
1924 src
= mputprintf(src
,
1925 "int %s::JSON_encode_negtest(const Erroneous_descriptor_t* p_err_descr, "
1926 "const TTCN_Typedescriptor_t&, JSON_Tokenizer& p_tok) const\n"
1928 if (!sdef
->jsonAsValue
) {
1929 src
= mputstr(src
, " int enc_len = p_tok.put_next_token(JSON_TOKEN_OBJECT_START, NULL);\n\n");
1931 src
= mputstr(src
, " int enc_len = 0;\n\n");
1934 " const Erroneous_values_t* err_vals = NULL;\n"
1935 " const Erroneous_descriptor_t* emb_descr = NULL;\n"
1936 " switch(union_selection) {\n");
1938 for (i
= 0; i
< sdef
->nElements
; ++i
) {
1939 src
= mputprintf(src
,
1941 " err_vals = p_err_descr->get_field_err_values(%d);\n"
1942 " emb_descr = p_err_descr->get_field_emb_descr(%d);\n"
1943 " if (NULL != err_vals && NULL != err_vals->value) {\n"
1944 " if (NULL != err_vals->value->errval) {\n"
1945 " if(err_vals->value->raw){\n"
1946 " enc_len += err_vals->value->errval->JSON_encode_negtest_raw(p_tok);\n"
1948 " if (NULL == err_vals->value->type_descr) {\n"
1949 " TTCN_error(\"internal error: erroneous value typedescriptor missing\");\n"
1951 , selection_prefix
, sdef
->elements
[i
].name
, (int)i
, (int)i
);
1952 if (!sdef
->jsonAsValue
) {
1953 src
= mputprintf(src
, " enc_len += p_tok.put_next_token(JSON_TOKEN_NAME, \"%s\");\n"
1954 , sdef
->elements
[i
].jsonAlias
? sdef
->elements
[i
].jsonAlias
: sdef
->elements
[i
].dispname
);
1957 " enc_len += err_vals->value->errval->JSON_encode(*err_vals->value->type_descr, p_tok);\n"
1961 if (!sdef
->jsonAsValue
) {
1962 src
= mputprintf(src
, " enc_len += p_tok.put_next_token(JSON_TOKEN_NAME, \"%s\");\n"
1963 , sdef
->elements
[i
].jsonAlias
? sdef
->elements
[i
].jsonAlias
: sdef
->elements
[i
].dispname
);
1965 src
= mputprintf(src
,
1966 " if (NULL != emb_descr) {\n"
1967 " enc_len += field_%s->JSON_encode_negtest(emb_descr, %s_descr_, p_tok);\n"
1969 " enc_len += field_%s->JSON_encode(%s_descr_, p_tok);\n"
1973 , sdef
->elements
[i
].name
, sdef
->elements
[i
].typedescrname
1974 , sdef
->elements
[i
].name
, sdef
->elements
[i
].typedescrname
);
1976 src
= mputprintf(src
,
1978 " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND, \n"
1979 " \"Encoding an unbound value of type %s.\");\n"
1983 if (!sdef
->jsonAsValue
) {
1984 src
= mputstr(src
, " enc_len += p_tok.put_next_token(JSON_TOKEN_OBJECT_END, NULL);\n");
1987 " return enc_len;\n"
1992 src
= mputprintf(src
,
1993 "int %s::JSON_decode(const TTCN_Typedescriptor_t&, JSON_Tokenizer& p_tok, boolean p_silent)\n"
1995 " json_token_t j_token = JSON_TOKEN_NONE;\n"
1997 if (sdef
->jsonAsValue
) {
1999 " size_t buf_pos = p_tok.get_buf_pos();\n"
2000 " p_tok.get_next_token(&j_token, NULL, NULL);\n"
2001 " int ret_val = 0;\n"
2002 " switch(j_token) {\n"
2003 " case JSON_TOKEN_NUMBER: {\n");
2004 for (i
= 0; i
< sdef
->nElements
; ++i
) {
2005 if (JSON_NUMBER
& sdef
->elements
[i
].jsonValueType
) {
2006 src
= mputprintf(src
,
2007 " p_tok.set_buf_pos(buf_pos);\n"
2008 " ret_val = %s%s().JSON_decode(%s_descr_, p_tok, true);\n"
2009 " if (0 <= ret_val) {\n"
2010 " return ret_val;\n"
2012 , at_field
, sdef
->elements
[i
].name
, sdef
->elements
[i
].typedescrname
);
2016 " JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_AS_VALUE_ERROR, \"number\");\n"
2018 " return JSON_ERROR_FATAL;\n"
2020 " case JSON_TOKEN_STRING: {\n");
2021 for (i
= 0; i
< sdef
->nElements
; ++i
) {
2022 if (JSON_STRING
& sdef
->elements
[i
].jsonValueType
) {
2023 src
= mputprintf(src
,
2024 " p_tok.set_buf_pos(buf_pos);\n"
2025 " ret_val = %s%s().JSON_decode(%s_descr_, p_tok, true);\n"
2026 " if (0 <= ret_val) {\n"
2027 " return ret_val;\n"
2029 , at_field
, sdef
->elements
[i
].name
, sdef
->elements
[i
].typedescrname
);
2033 " JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_AS_VALUE_ERROR, \"string\");\n"
2035 " return JSON_ERROR_FATAL;\n"
2037 " case JSON_TOKEN_LITERAL_TRUE:\n"
2038 " case JSON_TOKEN_LITERAL_FALSE: {\n");
2039 for (i
= 0; i
< sdef
->nElements
; ++i
) {
2040 if (JSON_BOOLEAN
& sdef
->elements
[i
].jsonValueType
) {
2041 src
= mputprintf(src
,
2042 " p_tok.set_buf_pos(buf_pos);\n"
2043 " ret_val = %s%s().JSON_decode(%s_descr_, p_tok, true);\n"
2044 " if (0 <= ret_val) {\n"
2045 " return ret_val;\n"
2047 , at_field
, sdef
->elements
[i
].name
, sdef
->elements
[i
].typedescrname
);
2051 " char* literal_str = mprintf(\"literal (%s)\",\n"
2052 " (JSON_TOKEN_LITERAL_TRUE == j_token) ? \"true\" : \"false\");\n"
2053 " JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_AS_VALUE_ERROR, literal_str);\n"
2054 " Free(literal_str);\n"
2056 " return JSON_ERROR_FATAL;\n"
2058 " case JSON_TOKEN_ARRAY_START: {\n");
2059 for (i
= 0; i
< sdef
->nElements
; ++i
) {
2060 if (JSON_ARRAY
& sdef
->elements
[i
].jsonValueType
) {
2061 src
= mputprintf(src
,
2062 " p_tok.set_buf_pos(buf_pos);\n"
2063 " ret_val = %s%s().JSON_decode(%s_descr_, p_tok, true);\n"
2064 " if (0 <= ret_val) {\n"
2065 " return ret_val;\n"
2067 , at_field
, sdef
->elements
[i
].name
, sdef
->elements
[i
].typedescrname
);
2071 " JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_AS_VALUE_ERROR, \"array\");\n"
2073 " return JSON_ERROR_FATAL;\n"
2075 " case JSON_TOKEN_OBJECT_START: {\n");
2076 for (i
= 0; i
< sdef
->nElements
; ++i
) {
2077 if (JSON_OBJECT
& sdef
->elements
[i
].jsonValueType
) {
2078 src
= mputprintf(src
,
2079 " p_tok.set_buf_pos(buf_pos);\n"
2080 " ret_val = %s%s().JSON_decode(%s_descr_, p_tok, true);\n"
2081 " if (0 <= ret_val) {\n"
2082 " return ret_val;\n"
2084 , at_field
, sdef
->elements
[i
].name
, sdef
->elements
[i
].typedescrname
);
2088 " JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_AS_VALUE_ERROR, \"object\");\n"
2090 " return JSON_ERROR_FATAL;\n"
2092 " case JSON_TOKEN_LITERAL_NULL: {\n");
2093 for (i
= 0; i
< sdef
->nElements
; ++i
) {
2094 if (JSON_NULL
& sdef
->elements
[i
].jsonValueType
) {
2095 src
= mputprintf(src
,
2096 " p_tok.set_buf_pos(buf_pos);\n"
2097 " ret_val = %s%s().JSON_decode(%s_descr_, p_tok, true);\n"
2098 " if (0 <= ret_val) {\n"
2099 " return ret_val;\n"
2101 , at_field
, sdef
->elements
[i
].name
, sdef
->elements
[i
].typedescrname
);
2106 // the caller might be able to decode the null value if it's an optional field
2107 // only return an invalid token error, not a fatal error
2108 " return JSON_ERROR_INVALID_TOKEN;\n"
2110 " case JSON_TOKEN_ERROR:\n"
2111 " JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_BAD_TOKEN_ERROR, \"\");\n"
2112 " return JSON_ERROR_FATAL;\n"
2114 " return JSON_ERROR_INVALID_TOKEN;\n"
2118 } else { // not "as value"
2119 src
= mputprintf(src
,
2120 " int dec_len = p_tok.get_next_token(&j_token, NULL, NULL);\n"
2121 " if (JSON_TOKEN_ERROR == j_token) {\n"
2122 " JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_BAD_TOKEN_ERROR, \"\");\n"
2123 " return JSON_ERROR_FATAL;\n"
2125 " else if (JSON_TOKEN_OBJECT_START != j_token) {\n"
2126 " return JSON_ERROR_INVALID_TOKEN;\n"
2128 " char* fld_name = 0;\n"
2129 " size_t name_len = 0;\n"
2130 " dec_len += p_tok.get_next_token(&j_token, &fld_name, &name_len);\n"
2131 " if (JSON_TOKEN_NAME != j_token) {\n"
2132 " JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_NAME_TOKEN_ERROR);\n"
2133 " return JSON_ERROR_FATAL;\n"
2135 " union_selection = %s;\n "
2137 for (i
= 0; i
< sdef
->nElements
; ++i
) {
2138 src
= mputprintf(src
,
2139 "if (0 == strncmp(fld_name, \"%s\", name_len)) {\n"
2140 " int ret_val = %s%s().JSON_decode(%s_descr_, p_tok, p_silent);\n"
2141 " if (0 > ret_val) {\n"
2142 " if (JSON_ERROR_INVALID_TOKEN) {\n"
2143 " JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_FIELD_TOKEN_ERROR, \"%s\");\n"
2145 " return JSON_ERROR_FATAL;\n"
2147 " dec_len += ret_val;\n"
2150 , sdef
->elements
[i
].jsonAlias
? sdef
->elements
[i
].jsonAlias
: sdef
->elements
[i
].dispname
2151 , at_field
, sdef
->elements
[i
].name
, sdef
->elements
[i
].typedescrname
2152 , sdef
->elements
[i
].dispname
);
2156 " char* fld_name2 = mcopystrn(fld_name, name_len);\n"
2157 " JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_INVALID_NAME_ERROR, fld_name2);\n"
2158 " Free(fld_name2);\n"
2159 " return JSON_ERROR_FATAL;\n"
2162 " dec_len += p_tok.get_next_token(&j_token, NULL, NULL);\n"
2163 " if (JSON_TOKEN_OBJECT_END != j_token) {\n"
2164 " JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_STATIC_OBJECT_END_TOKEN_ERROR, \"\");\n"
2165 " return JSON_ERROR_FATAL;\n"
2167 " return dec_len;\n"
2172 /* end of class definition */
2173 def
= mputstr(def
, "};\n\n");
2175 output
->header
.class_defs
= mputstr(output
->header
.class_defs
, def
);
2178 output
->source
.methods
= mputstr(output
->source
.methods
, src
);
2181 Free(selection_type
);
2182 Free(unbound_value
);
2183 Free(selection_prefix
);
2187 void defUnionTemplate(const struct_def
*sdef
, output_struct
*output
)
2190 const char *name
= sdef
->name
, *dispname
= sdef
->dispname
;
2191 const char *at_field
= sdef
->kind
==ANYTYPE
? "AT_" : "";
2192 char *def
= NULL
, *src
= NULL
;
2194 char *selection_type
, *unbound_value
, *selection_prefix
;
2195 selection_type
= mprintf("%s::union_selection_type", name
);
2196 unbound_value
= mprintf("%s::UNBOUND_VALUE", name
);
2197 selection_prefix
= mprintf("%s::ALT", name
);
2199 /* template class */
2201 output
->header
.class_decls
= mputprintf(output
->header
.class_decls
,
2202 "class %s_template;\n", name
);
2204 /* template class header and data members */
2205 def
= mputprintf(def
, "class %s_template : public Base_Template {\n"
2208 "%s union_selection;\n"
2209 "union {\n", name
, selection_type
);
2210 for (i
= 0; i
< sdef
->nElements
; i
++) {
2211 def
= mputprintf(def
, "%s_template *field_%s;\n",
2212 sdef
->elements
[i
].type
, sdef
->elements
[i
].name
);
2214 def
= mputprintf(def
, "};\n"
2217 "unsigned int n_values;\n"
2218 "%s_template *list_value;\n"
2221 if (use_runtime_2
) {
2223 "Erroneous_descriptor_t* err_descr;\n");
2226 /* copy_value function */
2227 def
= mputprintf(def
, "void copy_value(const %s& other_value);\n\n", name
);
2228 src
= mputprintf(src
, "void %s_template::copy_value(const %s& other_value)\n"
2230 "single_value.union_selection = other_value.get_selection();\n"
2231 "switch (single_value.union_selection) {\n", name
, name
);
2232 for (i
= 0; i
<sdef
->nElements
; i
++) {
2233 src
= mputprintf(src
, "case %s_%s:\n"
2234 "single_value.field_%s = new %s_template(other_value.%s%s());\n"
2235 "break;\n", selection_prefix
, sdef
->elements
[i
].name
,
2236 sdef
->elements
[i
].name
, sdef
->elements
[i
].type
,
2237 at_field
, sdef
->elements
[i
].name
);
2239 src
= mputprintf(src
, "default:\n"
2240 "TTCN_error(\"Initializing a template with an unbound value of type "
2243 "set_selection(SPECIFIC_VALUE);\n"
2246 use_runtime_2
? "err_descr = other_value.get_err_descr();\n" : "");
2248 /* copy_template function */
2249 def
= mputprintf(def
, "void copy_template(const %s_template& "
2250 "other_value);\n", name
);
2251 src
= mputprintf(src
, "void %s_template::copy_template(const "
2252 "%s_template& other_value)\n"
2254 "switch (other_value.template_selection) {\n"
2255 "case SPECIFIC_VALUE:\n"
2256 "single_value.union_selection = "
2257 "other_value.single_value.union_selection;\n"
2258 "switch (single_value.union_selection) {\n", name
, name
);
2259 for (i
= 0; i
< sdef
->nElements
; i
++) {
2260 src
= mputprintf(src
, "case %s_%s:\n"
2261 "single_value.field_%s = "
2262 "new %s_template(*other_value.single_value.field_%s);\n"
2263 "break;\n", selection_prefix
, sdef
->elements
[i
].name
,
2264 sdef
->elements
[i
].name
, sdef
->elements
[i
].type
, sdef
->elements
[i
].name
);
2266 src
= mputprintf(src
, "default:\n"
2267 "TTCN_error(\"Internal error: Invalid union selector in a specific value "
2268 "when copying a template of type %s.\");\n"
2270 "case OMIT_VALUE:\n"
2272 "case ANY_OR_OMIT:\n"
2274 "case VALUE_LIST:\n"
2275 "case COMPLEMENTED_LIST:\n"
2276 "value_list.n_values = other_value.value_list.n_values;\n"
2277 "value_list.list_value = new %s_template[value_list.n_values];\n"
2278 "for (unsigned int list_count = 0; list_count < value_list.n_values; "
2280 "value_list.list_value[list_count].copy_template("
2281 "other_value.value_list.list_value[list_count]);\n"
2284 "TTCN_error(\"Copying an uninitialized template of union type %s.\");\n"
2286 "set_selection(other_value);\n"
2288 "}\n\n", dispname
, name
, dispname
,
2289 use_runtime_2
? "err_descr = other_value.err_descr;\n" : "");
2291 /* default constructor */
2292 def
= mputprintf(def
, "\npublic:\n"
2293 "%s_template();\n", name
);
2294 src
= mputprintf(src
, "%s_template::%s_template()%s\n"
2296 "}\n\n", name
, name
,
2297 use_runtime_2
? ": err_descr(NULL)" : "");
2299 /* constructor (template_sel) */
2300 def
= mputprintf(def
, "%s_template(template_sel other_value);\n", name
);
2301 src
= mputprintf(src
, "%s_template::%s_template(template_sel other_value)\n"
2302 " : Base_Template(other_value)%s\n"
2304 "check_single_selection(other_value);\n"
2305 "}\n\n", name
, name
,
2306 use_runtime_2
? ", err_descr(NULL)" : "");
2308 /* constructor (value) */
2309 def
= mputprintf(def
, "%s_template(const %s& other_value);\n", name
, name
);
2310 src
= mputprintf(src
, "%s_template::%s_template(const %s& other_value)\n"
2312 "copy_value(other_value);\n"
2313 "}\n\n", name
, name
, name
);
2315 /* constructor (optional value) */
2316 def
= mputprintf(def
, "%s_template(const OPTIONAL<%s>& other_value);\n", name
,
2318 src
= mputprintf(src
, "%s_template::%s_template(const OPTIONAL<%s>& "
2321 "switch (other_value.get_selection()) {\n"
2322 "case OPTIONAL_PRESENT:\n"
2323 "copy_value((const %s&)other_value);\n"
2325 "case OPTIONAL_OMIT:\n"
2326 "set_selection(OMIT_VALUE);\n"
2330 "TTCN_error(\"Creating a template of union type %s from an unbound "
2331 "optional field.\");\n"
2333 "}\n\n", name
, name
, name
, name
,
2334 use_runtime_2
? "err_descr = NULL;\n" : "",
2337 /* copy constructor */
2338 def
= mputprintf(def
, "%s_template(const %s_template& other_value);\n", name
,
2340 src
= mputprintf(src
, "%s_template::%s_template(const %s_template& "
2342 ": Base_Template()" /* yes, the base class _default_ constructor */
2344 "copy_template(other_value);\n"
2345 "}\n\n", name
, name
, name
);
2348 def
= mputprintf(def
, "~%s_template();\n", name
);
2349 src
= mputprintf(src
, "%s_template::~%s_template()\n"
2352 "}\n\n", name
, name
);
2354 /* clean_up function */
2355 def
= mputstr(def
, "void clean_up();\n");
2356 src
= mputprintf(src
, "void %s_template::clean_up()\n"
2358 "switch (template_selection) {\n"
2359 "case SPECIFIC_VALUE:\n"
2360 "switch (single_value.union_selection) {\n", name
);
2361 for (i
= 0; i
< sdef
->nElements
; i
++) {
2362 src
= mputprintf(src
, "case %s_%s:\n"
2363 "delete single_value.field_%s;\n",
2364 selection_prefix
, sdef
->elements
[i
].name
, sdef
->elements
[i
].name
);
2365 if (i
< sdef
->nElements
- 1) src
= mputstr(src
, "break;\n");
2367 src
= mputstr(src
, "default:\n"
2371 "case VALUE_LIST:\n"
2372 "case COMPLEMENTED_LIST:\n"
2373 "delete [] value_list.list_value;\n"
2377 "template_selection = UNINITIALIZED_TEMPLATE;\n"
2380 /* assignment operator (template_sel) */
2381 def
= mputprintf(def
, "%s_template& operator=(template_sel other_value);\n",
2383 src
= mputprintf(src
,
2384 "%s_template& %s_template::operator=(template_sel "
2387 "check_single_selection(other_value);\n"
2389 "set_selection(other_value);\n"
2392 "}\n\n", name
, name
, use_runtime_2
? "err_descr = NULL;\n" : "");
2394 /* assignment operator (value) */
2395 def
= mputprintf(def
, "%s_template& operator=(const %s& other_value);\n",
2397 src
= mputprintf(src
, "%s_template& %s_template::operator=(const %s& "
2401 "copy_value(other_value);\n"
2403 "}\n\n", name
, name
, name
);
2405 /* assignment operator <- optional value */
2406 def
= mputprintf(def
, "%s_template& operator=(const OPTIONAL<%s>& "
2407 "other_value);\n", name
, name
);
2408 src
= mputprintf(src
,
2409 "%s_template& %s_template::operator=(const OPTIONAL<%s>& other_value)\n"
2412 "switch (other_value.get_selection()) {\n"
2413 "case OPTIONAL_PRESENT:\n"
2414 "copy_value((const %s&)other_value);\n"
2416 "case OPTIONAL_OMIT:\n"
2417 "set_selection(OMIT_VALUE);\n"
2421 "TTCN_error(\"Assignment of an unbound optional field to a template of "
2422 "union type %s.\");\n"
2425 "}\n\n", name
, name
, name
, name
,
2426 use_runtime_2
? "err_descr = NULL;\n" : "", dispname
);
2428 /* assignment operator (template) */
2429 def
= mputprintf(def
, "%s_template& operator=(const %s_template& "
2430 "other_value);\n", name
, name
);
2431 src
= mputprintf(src
,
2432 "%s_template& %s_template::operator=(const %s_template& other_value)\n"
2434 "if (&other_value != this) {\n"
2436 "copy_template(other_value);\n"
2439 "}\n\n", name
, name
, name
);
2441 /* match function */
2442 def
= mputprintf(def
, "boolean match(const %s& other_value, boolean legacy "
2443 "= FALSE) const;\n", name
);
2444 src
= mputprintf(src
, "boolean %s_template::match(const %s& other_value, "
2445 "boolean legacy) const\n"
2447 "if (!other_value.is_bound()) return FALSE;\n"
2448 "switch (template_selection) {\n"
2450 "case ANY_OR_OMIT:\n"
2452 "case OMIT_VALUE:\n"
2454 "case SPECIFIC_VALUE:\n"
2456 "%s value_selection = other_value.get_selection();\n"
2457 "if (value_selection == %s) return FALSE;\n"
2458 "if (value_selection != single_value.union_selection) return FALSE;\n"
2459 "switch (value_selection) {\n", name
, name
, selection_type
, unbound_value
);
2460 for (i
= 0; i
< sdef
->nElements
; i
++) {
2461 src
= mputprintf(src
, "case %s_%s:\n"
2462 "return single_value.field_%s->match(other_value.%s%s(), legacy);\n",
2463 selection_prefix
, sdef
->elements
[i
].name
, sdef
->elements
[i
].name
,
2464 at_field
, sdef
->elements
[i
].name
);
2466 src
= mputprintf(src
, "default:\n"
2467 "TTCN_error(\"Internal error: Invalid selector in a specific value when "
2468 "matching a template of union type %s.\");\n"
2471 "case VALUE_LIST:\n"
2472 "case COMPLEMENTED_LIST:\n"
2473 "for (unsigned int list_count = 0; list_count < value_list.n_values; "
2475 "if (value_list.list_value[list_count].match(other_value, legacy)) "
2476 "return template_selection == VALUE_LIST;\n"
2477 "return template_selection == COMPLEMENTED_LIST;\n"
2479 "TTCN_error (\"Matching an uninitialized template of union type %s.\");\n"
2482 "}\n\n", dispname
, dispname
);
2485 def
= mputstr(def
, "boolean is_value() const;");
2486 src
= mputprintf(src
, "boolean %s_template::is_value() const\n"
2488 "if (template_selection != SPECIFIC_VALUE || is_ifpresent) return false;\n"
2489 "switch (single_value.union_selection) {\n"
2491 for (i
= 0; i
< sdef
->nElements
; i
++) {
2492 src
= mputprintf(src
, "case %s_%s:\n"
2493 "return single_value.field_%s->is_value();\n", selection_prefix
,
2494 sdef
->elements
[i
].name
, sdef
->elements
[i
].name
);
2496 src
= mputprintf(src
, "default:\n"
2497 "TTCN_error(\"Internal error: Invalid selector in a specific value when "
2498 "performing is_value operation on a template of union type %s.\");\n"
2502 /* valueof member function */
2503 def
= mputprintf(def
, "%s valueof() const;\n", name
);
2504 src
= mputprintf(src
, "%s %s_template::valueof() const\n"
2506 "if (template_selection != SPECIFIC_VALUE || is_ifpresent)\n"
2507 "TTCN_error(\"Performing valueof or send operation on a non-specific "
2508 "template of union type %s.\");\n"
2510 "switch (single_value.union_selection) {\n", name
, name
, dispname
, name
);
2511 for (i
= 0; i
< sdef
->nElements
; i
++) {
2512 src
= mputprintf(src
, "case %s_%s:\n"
2513 "ret_val.%s%s() = single_value.field_%s->valueof();\n"
2514 "break;\n", selection_prefix
, sdef
->elements
[i
].name
,
2515 at_field
, sdef
->elements
[i
].name
, sdef
->elements
[i
].name
);
2517 src
= mputprintf(src
, "default:\n"
2518 "TTCN_error(\"Internal error: Invalid selector in a specific value when "
2519 "performing valueof operation on a template of union type %s.\");\n"
2524 use_runtime_2
? "ret_val.set_err_descr(err_descr);\n" : "");
2526 /* list_item(int) function */
2527 def
= mputprintf(def
, "%s_template& list_item(unsigned int list_index) "
2529 src
= mputprintf(src
,
2530 "%s_template& %s_template::list_item(unsigned int list_index) const\n"
2532 "if (template_selection != VALUE_LIST && "
2533 "template_selection != COMPLEMENTED_LIST) TTCN_error(\"Internal error: "
2534 "Accessing a list element of a non-list template of union type %s.\");\n"
2535 "if (list_index >= value_list.n_values) "
2536 "TTCN_error(\"Internal error: Index overflow in a value list template "
2537 "of union type %s.\");\n"
2538 "return value_list.list_value[list_index];\n"
2539 "}\n", name
, name
, dispname
, dispname
);
2541 /* void set_type(template_sel, int) function */
2542 def
= mputstr(def
, "void set_type(template_sel template_type, "
2543 "unsigned int list_length);\n");
2544 src
= mputprintf(src
,
2545 "void %s_template::set_type(template_sel template_type, "
2546 "unsigned int list_length)\n"
2548 "if (template_type != VALUE_LIST && template_type != COMPLEMENTED_LIST) "
2549 "TTCN_error (\"Internal error: Setting an invalid list for a template "
2550 "of union type %s.\");\n"
2552 "set_selection(template_type);\n"
2553 "value_list.n_values = list_length;\n"
2554 "value_list.list_value = new %s_template[list_length];\n"
2555 "}\n\n", name
, dispname
, name
);
2557 /* field access functions */
2558 for (i
= 0; i
< sdef
->nElements
; i
++) {
2559 def
= mputprintf(def
, "%s_template& %s%s();\n", sdef
->elements
[i
].type
,
2560 at_field
, sdef
->elements
[i
].name
);
2561 src
= mputprintf(src
, "%s_template& %s_template::%s%s()\n"
2563 "if (template_selection != SPECIFIC_VALUE || "
2564 "single_value.union_selection != %s_%s) {\n"
2565 "template_sel old_selection = template_selection;\n"
2567 "if (old_selection == ANY_VALUE || old_selection == ANY_OR_OMIT) "
2568 "single_value.field_%s = new %s_template(ANY_VALUE);\n"
2569 "else single_value.field_%s = new %s_template;\n"
2570 "single_value.union_selection = %s_%s;\n"
2571 "set_selection(SPECIFIC_VALUE);\n"
2573 "return *single_value.field_%s;\n"
2574 "}\n\n", sdef
->elements
[i
].type
, name
, at_field
, sdef
->elements
[i
].name
,
2575 selection_prefix
, sdef
->elements
[i
].name
, sdef
->elements
[i
].name
,
2576 sdef
->elements
[i
].type
, sdef
->elements
[i
].name
, sdef
->elements
[i
].type
,
2577 selection_prefix
, sdef
->elements
[i
].name
, sdef
->elements
[i
].name
);
2579 def
= mputprintf(def
, "const %s_template& %s%s() const;\n",
2580 sdef
->elements
[i
].type
, at_field
, sdef
->elements
[i
].name
);
2581 src
= mputprintf(src
, "const %s_template& %s_template::%s%s() const\n"
2583 "if (template_selection != SPECIFIC_VALUE) TTCN_error(\"Accessing field "
2584 "%s in a non-specific template of union type %s.\");\n"
2585 "if (single_value.union_selection != %s_%s) "
2586 "TTCN_error(\"Accessing non-selected field %s in a template of union "
2588 "return *single_value.field_%s;\n"
2589 "}\n\n", sdef
->elements
[i
].type
, name
, at_field
, sdef
->elements
[i
].name
,
2590 sdef
->elements
[i
].dispname
, dispname
, selection_prefix
,
2591 sdef
->elements
[i
].name
, sdef
->elements
[i
].dispname
, dispname
,
2592 sdef
->elements
[i
].name
);
2595 /* ischosen function */
2596 def
= mputprintf(def
, "boolean ischosen(%s checked_selection) const;\n",
2598 src
= mputprintf(src
, "boolean %s_template::ischosen(%s checked_selection) "
2601 "if (checked_selection == %s) TTCN_error(\"Internal error: Performing "
2602 "ischosen() operation on an invalid field of union type %s.\");\n"
2603 "switch (template_selection) {\n"
2604 "case SPECIFIC_VALUE:\n"
2605 "if (single_value.union_selection == %s) TTCN_error(\"Internal error: "
2606 "Invalid selector in a specific value when performing ischosen() "
2607 "operation on a template of union type %s.\");\n"
2608 "return single_value.union_selection == checked_selection;\n"
2609 "case VALUE_LIST:\n"
2611 "if (value_list.n_values < 1)\n"
2612 "TTCN_error(\"Internal error: Performing ischosen() operation on a "
2613 "template of union type %s containing an empty list.\");\n"
2614 "boolean ret_val = "
2615 "value_list.list_value[0].ischosen(checked_selection);\n"
2616 "boolean all_same = TRUE;\n"
2617 "for (unsigned int list_count = 1; list_count < value_list.n_values; "
2619 "if (value_list.list_value[list_count].ischosen(checked_selection) != "
2621 "all_same = FALSE;\n"
2625 "if (all_same) return ret_val;\n"
2628 "case ANY_OR_OMIT:\n"
2629 "case OMIT_VALUE:\n"
2630 "case COMPLEMENTED_LIST:\n"
2631 "TTCN_error(\"Performing ischosen() operation on a template of union type "
2632 "%s, which does not determine unambiguously the chosen field of the "
2633 "matching values.\");\n"
2635 "TTCN_error(\"Performing ischosen() operation on an uninitialized "
2636 "template of union type %s\");\n"
2639 "}\n\n", name
, selection_type
, unbound_value
, dispname
, unbound_value
,
2640 dispname
, dispname
, dispname
, dispname
);
2642 if (use_runtime_2
) {
2644 "void set_err_descr(Erroneous_descriptor_t* p_err_descr) { err_descr=p_err_descr; }\n");
2645 /** virtual stuff */
2647 "void valueofv(Base_Type* value) const;\n"
2648 "void set_value(template_sel other_value);\n"
2649 "void copy_value(const Base_Type* other_value);\n"
2650 "Base_Template* clone() const;\n"
2651 "const TTCN_Typedescriptor_t* get_descriptor() const;\n"
2652 "boolean matchv(const Base_Type* other_value, boolean legacy) const;\n"
2653 "void log_matchv(const Base_Type* match_value, boolean legacy) const;\n");
2654 src
= mputprintf(src
,
2655 "void %s_template::valueofv(Base_Type* value) const "
2656 "{ *(static_cast<%s*>(value)) = valueof(); }\n"
2657 "void %s_template::set_value(template_sel other_value) "
2658 "{ *this = other_value; }\n"
2659 "void %s_template::copy_value(const Base_Type* other_value) "
2660 "{ *this = *(static_cast<const %s*>(other_value)); }\n"
2661 "Base_Template* %s_template::clone() const "
2662 "{ return new %s_template(*this); }\n"
2663 "const TTCN_Typedescriptor_t* %s_template::get_descriptor() const "
2664 "{ return &%s_descr_; }\n"
2665 "boolean %s_template::matchv(const Base_Type* other_value, "
2666 "boolean legacy) const "
2667 "{ return match(*(static_cast<const %s*>(other_value)), legacy); }\n"
2668 "void %s_template::log_matchv(const Base_Type* match_value, "
2669 "boolean legacy) const "
2670 " { log_match(*(static_cast<const %s*>(match_value)), legacy); }\n",
2681 def
= mputstr(def
, "void log() const;\n");
2682 src
= mputprintf(src
,"void %s_template::log() const\n"
2684 "switch (template_selection) {\n"
2685 "case SPECIFIC_VALUE:\n"
2686 "switch (single_value.union_selection) {\n", name
);
2687 for (i
= 0; i
< sdef
->nElements
; i
++) {
2688 src
= mputprintf(src
, "case %s_%s:\n"
2689 "TTCN_Logger::log_event_str(\"{ %s := \");\n"
2690 "single_value.field_%s->log();\n"
2691 "TTCN_Logger::log_event_str(\" }\");\n"
2692 "break;\n", selection_prefix
, sdef
->elements
[i
].name
,
2693 sdef
->elements
[i
].dispname
, sdef
->elements
[i
].name
);
2695 src
= mputstr(src
, "default:\n"
2696 "TTCN_Logger::log_event_str(\"<invalid selector>\");\n"
2699 "case COMPLEMENTED_LIST:\n"
2700 "TTCN_Logger::log_event_str(\"complement \");\n"
2701 "case VALUE_LIST:\n"
2702 "TTCN_Logger::log_char('(');\n"
2703 "for (unsigned int list_count = 0; list_count < value_list.n_values; "
2705 "if (list_count > 0) TTCN_Logger::log_event_str(\", \");\n"
2706 "value_list.list_value[list_count].log();\n"
2708 "TTCN_Logger::log_char(')');\n"
2713 "log_ifpresent();\n");
2714 if (use_runtime_2
) {
2715 src
= mputstr(src
, "if (err_descr) err_descr->log();\n");
2717 src
= mputstr(src
, "}\n\n");
2719 /* log_match function */
2720 def
= mputprintf(def
, "void log_match(const %s& match_value, "
2721 "boolean legacy = FALSE) const;\n", name
);
2722 src
= mputprintf(src
,
2723 "void %s_template::log_match(const %s& match_value, boolean legacy) const\n"
2725 "if(TTCN_Logger::VERBOSITY_COMPACT == TTCN_Logger::get_matching_verbosity() "
2726 "&& match(match_value, legacy)){\n"
2727 "TTCN_Logger::print_logmatch_buffer();\n"
2728 "TTCN_Logger::log_event_str(\" matched\");\n"
2731 "if (template_selection == SPECIFIC_VALUE && "
2732 "single_value.union_selection == match_value.get_selection()) {\n"
2733 "switch (single_value.union_selection) {\n", name
, name
);
2734 for (i
= 0; i
< sdef
->nElements
; i
++) {
2735 src
= mputprintf(src
, "case %s_%s:\n"
2736 "if(TTCN_Logger::VERBOSITY_COMPACT == TTCN_Logger::get_matching_verbosity()){\n"
2737 "TTCN_Logger::log_logmatch_info(\".%s\");\n"
2738 "single_value.field_%s->log_match(match_value.%s%s(), legacy);\n"
2740 "TTCN_Logger::log_event_str(\"{ %s := \");\n"
2741 "single_value.field_%s->log_match(match_value.%s%s(), legacy);\n"
2742 "TTCN_Logger::log_event_str(\" }\");\n"
2744 "break;\n", selection_prefix
, sdef
->elements
[i
].name
,
2745 sdef
->elements
[i
].dispname
,
2746 sdef
->elements
[i
].name
, at_field
, sdef
->elements
[i
].name
,
2747 sdef
->elements
[i
].dispname
, sdef
->elements
[i
].name
,
2748 at_field
, sdef
->elements
[i
].name
);
2750 src
= mputstr(src
, "default:\n"
2751 "TTCN_Logger::print_logmatch_buffer();\n"
2752 "TTCN_Logger::log_event_str(\"<invalid selector>\");\n"
2755 "TTCN_Logger::print_logmatch_buffer();\n"
2756 "match_value.log();\n"
2757 "TTCN_Logger::log_event_str(\" with \");\n"
2759 "if (match(match_value, legacy)) TTCN_Logger::log_event_str(\" matched\");\n"
2760 "else TTCN_Logger::log_event_str(\" unmatched\");\n"
2764 /* encode_text function */
2765 def
= mputstr(def
, "void encode_text(Text_Buf& text_buf) const;\n");
2766 src
= mputprintf(src
,
2767 "void %s_template::encode_text(Text_Buf& text_buf) const\n"
2769 "encode_text_base(text_buf);\n"
2770 "switch (template_selection) {\n"
2771 "case SPECIFIC_VALUE:\n"
2772 "text_buf.push_int(single_value.union_selection);\n"
2773 "switch (single_value.union_selection) {\n", name
);
2774 for (i
= 0; i
< sdef
->nElements
; i
++) {
2775 src
= mputprintf(src
, "case %s_%s:\n"
2776 "single_value.field_%s->encode_text(text_buf);\n"
2777 "break;\n", selection_prefix
, sdef
->elements
[i
].name
,
2778 sdef
->elements
[i
].name
);
2780 src
= mputprintf(src
, "default:\n"
2781 "TTCN_error(\"Internal error: Invalid selector in a specific value when "
2782 "encoding a template of union type %s.\");\n"
2784 "case OMIT_VALUE:\n"
2786 "case ANY_OR_OMIT:\n"
2788 "case VALUE_LIST:\n"
2789 "case COMPLEMENTED_LIST:\n"
2790 "text_buf.push_int(value_list.n_values);\n"
2791 "for (unsigned int list_count = 0; list_count < value_list.n_values; "
2793 "value_list.list_value[list_count].encode_text(text_buf);\n"
2796 "TTCN_error(\"Text encoder: Encoding an uninitialized template of type "
2799 "}\n\n", dispname
, dispname
);
2801 /* decode_text function */
2802 def
= mputstr(def
, "void decode_text(Text_Buf& text_buf);\n");
2803 src
= mputprintf(src
, "void %s_template::decode_text(Text_Buf& text_buf)\n"
2806 "decode_text_base(text_buf);\n"
2807 "switch (template_selection) {\n"
2808 "case SPECIFIC_VALUE:\n"
2810 "single_value.union_selection = %s;\n"
2811 "%s new_selection = (%s)text_buf.pull_int().get_val();\n"
2812 "switch (new_selection) {\n", name
, unbound_value
, selection_type
,
2814 for (i
= 0; i
< sdef
->nElements
; i
++) {
2815 src
= mputprintf(src
, "case %s_%s:\n"
2816 "single_value.field_%s = new %s_template;\n"
2817 "single_value.field_%s->decode_text(text_buf);\n"
2818 "break;\n", selection_prefix
, sdef
->elements
[i
].name
,
2819 sdef
->elements
[i
].name
, sdef
->elements
[i
].type
, sdef
->elements
[i
].name
);
2821 src
= mputprintf(src
, "default:\n"
2822 "TTCN_error(\"Text decoder: Unrecognized union selector was received for "
2823 "a template of type %s.\");\n"
2825 "single_value.union_selection = new_selection;\n"
2827 "case OMIT_VALUE:\n"
2829 "case ANY_OR_OMIT:\n"
2831 "case VALUE_LIST:\n"
2832 "case COMPLEMENTED_LIST:\n"
2833 "value_list.n_values = text_buf.pull_int().get_val();\n"
2834 "value_list.list_value = new %s_template[value_list.n_values];\n"
2835 "for (unsigned int list_count = 0; list_count < value_list.n_values; "
2837 "value_list.list_value[list_count].decode_text(text_buf);\n"
2840 "TTCN_error(\"Text decoder: Unrecognized selector was received in a "
2841 "template of type %s.\");\n"
2843 "}\n\n", dispname
, name
, dispname
);
2845 /* TTCN-3 ispresent() function */
2846 def
= mputstr(def
, "boolean is_present(boolean legacy = FALSE) const;\n");
2847 src
= mputprintf(src
,
2848 "boolean %s_template::is_present(boolean legacy) const\n"
2850 "if (template_selection==UNINITIALIZED_TEMPLATE) return FALSE;\n"
2851 "return !match_omit(legacy);\n"
2855 def
= mputstr(def
, "boolean match_omit(boolean legacy = FALSE) const;\n");
2856 src
= mputprintf(src
,
2857 "boolean %s_template::match_omit(boolean legacy) const\n"
2859 "if (is_ifpresent) return TRUE;\n"
2860 "switch (template_selection) {\n"
2861 "case OMIT_VALUE:\n"
2862 "case ANY_OR_OMIT:\n"
2864 "case VALUE_LIST:\n"
2865 "case COMPLEMENTED_LIST:\n"
2867 "for (unsigned int v_idx=0; v_idx<value_list.n_values; v_idx++)\n"
2868 "if (value_list.list_value[v_idx].match_omit())\n"
2869 "return template_selection==VALUE_LIST;\n"
2870 "return template_selection==COMPLEMENTED_LIST;\n"
2871 "} // else fall through\n"
2879 def
= mputstr(def
, "void set_param(Module_Param& param);\n");
2880 src
= mputprintf(src
,
2881 "void %s_template::set_param(Module_Param& param)\n"
2883 " if (dynamic_cast<Module_Param_Name*>(param.get_id()) != NULL &&\n"
2884 " param.get_id()->next_name()) {\n"
2885 // Haven't reached the end of the module parameter name
2886 // => the name refers to one of the fields, not to the whole union
2887 " char* param_field = param.get_id()->get_current_name();\n"
2888 " if (param_field[0] >= '0' && param_field[0] <= '9') {\n"
2889 " param.error(\"Unexpected array index in module parameter, expected a valid field\"\n"
2890 " \" name for union template type `%s'\");\n"
2892 " ", name
, dispname
);
2893 for (i
= 0; i
< sdef
->nElements
; i
++) {
2894 src
= mputprintf(src
,
2895 "if (strcmp(\"%s\", param_field) == 0) {\n"
2896 " %s%s().set_param(param);\n"
2899 sdef
->elements
[i
].dispname
, at_field
, sdef
->elements
[i
].name
);
2901 src
= mputprintf(src
,
2902 "param.error(\"Field `%%s' not found in union template type `%s'\", param_field);\n"
2904 " param.basic_check(Module_Param::BC_TEMPLATE, \"union template\");\n"
2905 " Module_Param_Ptr m_p = ¶m;\n"
2906 " if (param.get_type() == Module_Param::MP_Reference) {\n"
2907 " m_p = param.get_referenced_param();\n"
2909 " switch (m_p->get_type()) {\n"
2910 " case Module_Param::MP_Omit:\n"
2911 " *this = OMIT_VALUE;\n"
2913 " case Module_Param::MP_Any:\n"
2914 " *this = ANY_VALUE;\n"
2916 " case Module_Param::MP_AnyOrNone:\n"
2917 " *this = ANY_OR_OMIT;\n"
2919 " case Module_Param::MP_List_Template:\n"
2920 " case Module_Param::MP_ComplementList_Template: {\n"
2921 " %s_template new_temp;\n"
2922 " new_temp.set_type(m_p->get_type()==Module_Param::MP_List_Template ? "
2923 "VALUE_LIST : COMPLEMENTED_LIST, m_p->get_size());\n"
2924 " for (size_t p_i=0; p_i<m_p->get_size(); p_i++) {\n"
2925 " new_temp.list_item(p_i).set_param(*m_p->get_elem(p_i));\n"
2927 " *this = new_temp;\n"
2929 " case Module_Param::MP_Value_List:\n"
2930 " if (m_p->get_size()==0) break;\n" /* for backward compatibility */
2931 " param.type_error(\"union template\", \"%s\");\n"
2933 " case Module_Param::MP_Assignment_List: {\n"
2934 " Module_Param* mp_last = m_p->get_elem(m_p->get_size()-1);\n",
2935 dispname
, name
, dispname
);
2936 for (i
= 0; i
< sdef
->nElements
; i
++) {
2937 src
= mputprintf(src
,
2938 " if (!strcmp(mp_last->get_id()->get_name(), \"%s\")) {\n"
2939 " %s%s().set_param(*mp_last);\n"
2941 " }\n", sdef
->elements
[i
].dispname
, at_field
, sdef
->elements
[i
].name
);
2943 src
= mputprintf(src
,
2944 " mp_last->error(\"Field %%s does not exist in type %s.\", mp_last->get_id()->get_name());\n"
2947 " param.type_error(\"union template\", \"%s\");\n"
2949 " is_ifpresent = param.get_ifpresent() || m_p->get_ifpresent();\n"
2950 "}\n\n", dispname
, dispname
);
2953 def
= mputstr(def
, "Module_Param* get_param(Module_Param_Name& param_name) const;\n");
2954 src
= mputprintf(src
,
2955 "Module_Param* %s_template::get_param(Module_Param_Name& param_name) const\n"
2957 " if (param_name.next_name()) {\n"
2958 // Haven't reached the end of the module parameter name
2959 // => the name refers to one of the fields, not to the whole union
2960 " char* param_field = param_name.get_current_name();\n"
2961 " if (param_field[0] >= '0' && param_field[0] <= '9') {\n"
2962 " TTCN_error(\"Unexpected array index in module parameter reference, \"\n"
2963 " \"expected a valid field name for union template type `%s'\");\n"
2965 " ", name
, dispname
);
2966 for (i
= 0; i
< sdef
->nElements
; i
++) {
2967 src
= mputprintf(src
,
2968 "if (strcmp(\"%s\", param_field) == 0) {\n"
2969 " return %s%s().get_param(param_name);\n"
2971 sdef
->elements
[i
].dispname
, at_field
, sdef
->elements
[i
].name
);
2973 src
= mputprintf(src
,
2974 "TTCN_error(\"Field `%%s' not found in union type `%s'\", param_field);\n"
2976 " Module_Param* m_p = NULL;\n"
2977 " switch (template_selection) {\n"
2978 " case UNINITIALIZED_TEMPLATE:\n"
2979 " m_p = new Module_Param_Unbound();\n"
2981 " case OMIT_VALUE:\n"
2982 " m_p = new Module_Param_Omit();\n"
2984 " case ANY_VALUE:\n"
2985 " m_p = new Module_Param_Any();\n"
2987 " case ANY_OR_OMIT:\n"
2988 " m_p = new Module_Param_AnyOrNone();\n"
2990 " case SPECIFIC_VALUE: {\n"
2991 " Module_Param* mp_field = NULL;\n"
2992 " switch(single_value.union_selection) {\n"
2994 for (i
= 0; i
< sdef
->nElements
; ++i
) {
2995 src
= mputprintf(src
,
2997 " mp_field = single_value.field_%s->get_param(param_name);\n"
2998 " mp_field->set_id(new Module_Param_FieldName(mcopystr(\"%s\")));\n"
3000 , selection_prefix
, sdef
->elements
[i
].name
3001 , sdef
->elements
[i
].name
, sdef
->elements
[i
].dispname
);
3007 " m_p = new Module_Param_Assignment_List();\n"
3008 " m_p->add_elem(mp_field);\n"
3010 " case VALUE_LIST:\n"
3011 " case COMPLEMENTED_LIST: {\n"
3012 " if (template_selection == VALUE_LIST) {\n"
3013 " m_p = new Module_Param_List_Template();\n"
3016 " m_p = new Module_Param_ComplementList_Template();\n"
3018 " for (size_t i_i = 0; i_i < value_list.n_values; ++i_i) {\n"
3019 " m_p->add_elem(value_list.list_value[i_i].get_param(param_name));\n"
3025 " if (is_ifpresent) {\n"
3026 " m_p->set_ifpresent();\n"
3031 /* check template restriction */
3032 def
= mputstr(def
, "void check_restriction(template_res t_res, "
3033 "const char* t_name=NULL, boolean legacy = FALSE) const;\n");
3034 src
= mputprintf(src
,
3035 "void %s_template::check_restriction("
3036 "template_res t_res, const char* t_name, boolean legacy) const\n"
3038 "if (template_selection==UNINITIALIZED_TEMPLATE) return;\n"
3039 "switch ((t_name&&(t_res==TR_VALUE))?TR_OMIT:t_res) {\n"
3041 "if (template_selection==OMIT_VALUE) return;\n"
3043 "if (template_selection!=SPECIFIC_VALUE || is_ifpresent) break;\n"
3044 "switch (single_value.union_selection) {\n"
3046 for (i
= 0; i
< sdef
->nElements
; i
++) {
3047 src
= mputprintf(src
, "case %s_%s:\n"
3048 "single_value.field_%s->check_restriction("
3049 "t_res, t_name ? t_name : \"%s\");\n"
3051 selection_prefix
, sdef
->elements
[i
].name
,
3052 sdef
->elements
[i
].name
, dispname
);
3054 src
= mputprintf(src
, "default:\n"
3055 "TTCN_error(\"Internal error: Invalid selector in a specific value when "
3056 "performing check_restriction operation on a template of union type %s.\");\n"
3058 "case TR_PRESENT:\n"
3059 "if (!match_omit(legacy)) return;\n"
3064 "TTCN_error(\"Restriction `%%s' on template of type %%s violated.\", "
3065 "get_res_name(t_res), t_name ? t_name : \"%s\");\n"
3066 "}\n\n", dispname
, dispname
);
3068 def
= mputstr(def
, "};\n\n");
3070 output
->header
.class_defs
= mputstr(output
->header
.class_defs
, def
);
3073 output
->source
.methods
= mputstr(output
->source
.methods
, src
);
3076 Free(selection_type
);
3077 Free(unbound_value
);
3078 Free(selection_prefix
);