1 ///////////////////////////////////////////////////////////////////////////////
2 // Copyright (c) 2000-2014 Ericsson Telecom AB
3 // All rights reserved. This program and the accompanying materials
4 // are made available under the terms of the Eclipse Public License v1.0
5 // which accompanies this distribution, and is available at
6 // http://www.eclipse.org/legal/epl-v10.html
7 ///////////////////////////////////////////////////////////////////////////////
8 #include "../common/memory.h"
10 #include "record_of.h"
14 #include "ttcn3/compiler.h"
16 /** code generation for original runtime */
17 static void defRecordOfClass1(const struct_of_def
*sdef
, output_struct
*output
);
18 static void defRecordOfTemplate1(const struct_of_def
*sdef
, output_struct
*output
);
19 /** code generation for alternative runtime (TITAN_RUNTIME_2) */
20 static void defRecordOfClass2(const struct_of_def
*sdef
, output_struct
*output
);
21 static void defRecordOfTemplate2(const struct_of_def
*sdef
, output_struct
*output
);
23 void defRecordOfClass(const struct_of_def
*sdef
, output_struct
*output
)
25 if (use_runtime_2
) defRecordOfClass2(sdef
, output
);
26 else defRecordOfClass1(sdef
, output
);
29 void defRecordOfTemplate(const struct_of_def
*sdef
, output_struct
*output
)
31 if (use_runtime_2
) defRecordOfTemplate2(sdef
, output
);
32 else defRecordOfTemplate1(sdef
, output
);
35 /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
37 void defRecordOfClass1(const struct_of_def
*sdef
, output_struct
*output
)
39 char *def
= NULL
, *src
= NULL
;
40 const char *name
= sdef
->name
, *dispname
= sdef
->dispname
;
41 const char *type
= sdef
->type
;
42 boolean ber_needed
= sdef
->isASN1
&& enable_ber();
43 boolean raw_needed
= sdef
->hasRaw
&& enable_raw();
44 boolean text_needed
= sdef
->hasText
&& enable_text();
45 boolean xer_needed
= sdef
->hasXer
&& enable_xer();
46 boolean json_needed
= sdef
->hasJson
&& enable_json();
48 /* Class definition and private data members */
51 "// written by %s in " __FILE__
" at %d\n"
53 "class %s : public Base_Type {\n"
54 "struct recordof_setof_struct {\n"
57 "%s **value_elements;\n"
60 , __FUNCTION__
, __LINE__
64 /* constant unbound element */
65 def
= mputprintf(def
, "\nstatic const %s UNBOUND_ELEM;\n", type
);
66 src
= mputprintf(src
, "\nconst %s %s::UNBOUND_ELEM;\n", type
, name
);
68 /* private member functions */
71 "friend boolean operator==(null_type null_value, "
72 "const %s& other_value);\n", name
);
74 if (sdef
->kind
== SET_OF
) {
75 /* callback function for comparison */
76 def
= mputstr(def
, "static boolean compare_function("
77 "const Base_Type *left_ptr, int left_index, "
78 "const Base_Type *right_ptr, int right_index);\n");
79 src
= mputprintf(src
, "boolean %s::compare_function("
80 "const Base_Type *left_ptr, int left_index, "
81 "const Base_Type *right_ptr, int right_index)\n"
83 "if (((const %s*)left_ptr)->val_ptr == NULL) "
84 "TTCN_error(\"The left operand of comparison is an unbound value of "
86 "if (((const %s*)right_ptr)->val_ptr == NULL) "
87 "TTCN_error(\"The right operand of comparison is an unbound value of "
89 "if (((const %s*)left_ptr)->val_ptr->value_elements[left_index] != NULL){\n"
90 "if (((const %s*)right_ptr)->val_ptr->value_elements[right_index] != NULL){\n"
91 "return *((const %s*)left_ptr)->val_ptr->value_elements[left_index] == "
92 "*((const %s*)right_ptr)->val_ptr->value_elements[right_index];\n"
93 "} else return FALSE;\n"
95 "return ((const %s*)right_ptr)->val_ptr->value_elements[right_index] == NULL;\n"
97 "}\n\n", name
, name
, dispname
, name
, dispname
, name
, name
, name
, name
, name
);
100 /* public member functions */
101 def
= mputstr(def
, "\npublic:\n");
102 def
= mputprintf(def
, " typedef %s of_type;\n", sdef
->type
);
105 def
= mputprintf(def
, "%s();\n", name
);
106 src
= mputprintf(src
,
110 "}\n\n", name
, name
);
112 def
= mputprintf(def
, "%s(null_type other_value);\n", name
);
113 src
= mputprintf(src
,
114 "%s::%s(null_type)\n"
116 "val_ptr = new recordof_setof_struct;\n"
117 "val_ptr->ref_count = 1;\n"
118 "val_ptr->n_elements = 0;\n"
119 "val_ptr->value_elements = NULL;\n"
120 "}\n\n", name
, name
);
122 /* copy constructor */
123 def
= mputprintf(def
, "%s(const %s& other_value);\n", name
, name
);
124 src
= mputprintf(src
,
125 "%s::%s(const %s& other_value)\n"
127 "if (!other_value.is_bound()) "
128 "TTCN_error(\"Copying an unbound value of type %s.\");\n"
129 "val_ptr = other_value.val_ptr;\n"
130 "val_ptr->ref_count++;\n"
131 "}\n\n", name
, name
, name
, dispname
);
134 def
= mputprintf(def
, "~%s();\n\n", name
);
135 src
= mputprintf(src
,
139 "if (val_ptr != NULL) val_ptr = NULL;\n"
140 "}\n\n", name
, name
);
142 /* clean_up function */
143 def
= mputstr(def
, "void clean_up();\n");
146 "void %s::clean_up()\n"
148 "if (val_ptr != NULL) {\n"
149 "if (val_ptr->ref_count > 1) {\n"
150 "val_ptr->ref_count--;\n"
153 "else if (val_ptr->ref_count == 1) {\n"
154 "for (int elem_count = 0; elem_count < val_ptr->n_elements;\n"
156 "if (val_ptr->value_elements[elem_count] != NULL)\n"
157 "delete val_ptr->value_elements[elem_count];\n"
158 "free_pointers((void**)val_ptr->value_elements);\n"
163 "TTCN_error(\"Internal error: Invalid reference counter in a record "
164 "of/set of value.\");\n"
168 /* assignment operators */
169 def
= mputprintf(def
, "%s& operator=(null_type other_value);\n", name
);
170 src
= mputprintf(src
,
171 "%s& %s::operator=(null_type)\n"
174 "val_ptr = new recordof_setof_struct;\n"
175 "val_ptr->ref_count = 1;\n"
176 "val_ptr->n_elements = 0;\n"
177 "val_ptr->value_elements = NULL;\n"
179 "}\n\n", name
, name
);
181 def
= mputprintf(def
, "%s& operator=(const %s& other_value);\n\n",
183 src
= mputprintf(src
,
184 "%s& %s::operator=(const %s& other_value)\n"
186 "if (other_value.val_ptr == NULL) "
187 "TTCN_error(\"Assigning an unbound value of type %s.\");\n"
188 "if (this != &other_value) {\n"
190 "val_ptr = other_value.val_ptr;\n"
191 "val_ptr->ref_count++;\n"
194 "}\n\n", name
, name
, name
, dispname
);
196 /* comparison operators */
197 def
= mputstr(def
, "boolean operator==(null_type other_value) const;\n");
198 src
= mputprintf(src
,
199 "boolean %s::operator==(null_type) const\n"
201 "if (val_ptr == NULL)\n"
202 "TTCN_error(\"The left operand of comparison is an unbound value of "
204 "return val_ptr->n_elements == 0 ;\n"
205 "}\n\n", name
, dispname
);
207 def
= mputprintf(def
, "boolean operator==(const %s& other_value) const;\n",
209 src
= mputprintf(src
,
210 "boolean %s::operator==(const %s& other_value) const\n"
212 "if (val_ptr == NULL) "
213 "TTCN_error(\"The left operand of comparison is an unbound value of type "
215 "if (other_value.val_ptr == NULL) "
216 "TTCN_error(\"The right operand of comparison is an unbound value of type "
218 "if (val_ptr == other_value.val_ptr) return TRUE;\n", name
, name
,
220 if (sdef
->kind
== SET_OF
) {
222 "return compare_set_of(this, val_ptr->n_elements, &other_value, "
223 "(other_value.val_ptr)->n_elements, compare_function);\n");
227 "if (val_ptr->n_elements != (other_value.val_ptr)->n_elements)\n"
229 "for (int elem_count = 0; elem_count < val_ptr->n_elements; elem_count++){\n"
230 "if (val_ptr->value_elements[elem_count] != NULL){\n"
231 "if ((other_value.val_ptr)->value_elements[elem_count] != NULL){\n"
232 " if (*val_ptr->value_elements[elem_count] != "
233 "*(other_value.val_ptr)->value_elements[elem_count]) "
235 "} else return FALSE;\n"
237 "if ((other_value.val_ptr)->value_elements[elem_count] != NULL) "
243 src
= mputstr(src
, "}\n\n");
245 def
= mputstr(def
, "inline boolean operator!=(null_type other_value) const "
246 "{ return !(*this == other_value); }\n");
247 def
= mputprintf(def
, "inline boolean operator!=(const %s& other_value) "
248 "const { return !(*this == other_value); }\n\n", name
);
250 /* indexing operators */
251 /* Non-const operator[] is allowed to extend the record-of */
252 def
= mputprintf(def
, "%s& operator[](int index_value);\n", type
);
253 src
= mputprintf(src
,
254 "%s& %s::operator[](int index_value)\n"
256 "if (index_value < 0) TTCN_error(\"Accessing an element of type %s "
257 "using a negative index: %%d.\", index_value);\n"
258 "if (val_ptr == NULL) {\n"
259 "val_ptr = new recordof_setof_struct;\n"
260 "val_ptr->ref_count = 1;\n"
261 "val_ptr->n_elements = 0;\n"
262 "val_ptr->value_elements = NULL;\n"
263 "} else if (val_ptr->ref_count > 1) {\n" /* copy-on-write */
264 "struct recordof_setof_struct *new_val_ptr = new recordof_setof_struct;\n"
265 "new_val_ptr->ref_count = 1;\n"
266 "new_val_ptr->n_elements = (index_value >= val_ptr->n_elements) ? "
267 "index_value + 1 : val_ptr->n_elements;\n"
268 "new_val_ptr->value_elements = "
269 "(%s**)allocate_pointers(new_val_ptr->n_elements);\n"
270 "for (int elem_count = 0; elem_count < val_ptr->n_elements; "
272 "if (val_ptr->value_elements[elem_count] != NULL){\n"
273 "new_val_ptr->value_elements[elem_count] = "
274 "new %s(*(val_ptr->value_elements[elem_count]));\n"
278 "val_ptr = new_val_ptr;\n"
280 "if (index_value >= val_ptr->n_elements) set_size(index_value + 1);\n"
281 "if (val_ptr->value_elements[index_value] == NULL) {\n"
282 "val_ptr->value_elements[index_value] = new %s;\n"
284 "return *val_ptr->value_elements[index_value];\n"
285 "}\n\n", type
, name
, dispname
, type
, type
, type
);
287 def
= mputprintf(def
, "%s& operator[](const INTEGER& index_value);\n",
289 src
= mputprintf(src
,
290 "%s& %s::operator[](const INTEGER& index_value)\n"
292 "index_value.must_bound(\"Using an unbound integer value for indexing "
293 "a value of type %s.\");\n"
294 "return (*this)[(int)index_value];\n"
295 "}\n\n", type
, name
, dispname
);
297 /* Const operator[] throws an error if over-indexing */
298 def
= mputprintf(def
, "const %s& operator[](int index_value) const;\n",
300 src
= mputprintf(src
,
301 "const %s& %s::operator[](int index_value) const\n"
303 "if (val_ptr == NULL)\n"
304 "TTCN_error(\"Accessing an element in an unbound value of type %s.\");\n"
305 "if (index_value < 0) TTCN_error(\"Accessing an element of type %s "
306 "using a negative index: %%d.\", index_value);\n"
307 "if (index_value >= val_ptr->n_elements) TTCN_error(\"Index overflow in "
308 "a value of type %s: The index is %%d, but the value has only %%d "
309 "elements.\", index_value, val_ptr->n_elements);\n"
310 "return (val_ptr->value_elements[index_value] != NULL) ?\n"
311 "*val_ptr->value_elements[index_value] : UNBOUND_ELEM;\n"
312 "}\n\n", type
, name
, dispname
, dispname
, dispname
);
314 def
= mputprintf(def
, "const %s& operator[](const INTEGER& index_value) "
316 src
= mputprintf(src
,
317 "const %s& %s::operator[](const INTEGER& index_value) const\n"
319 "index_value.must_bound(\"Using an unbound integer value for indexing "
320 "a value of type %s.\");\n"
321 "return (*this)[(int)index_value];\n"
322 "}\n\n", type
, name
, dispname
);
324 /* rotation operators */
325 def
= mputprintf(def
,
326 "%s operator<<=(int rotate_count) const;\n"
327 "%s operator<<=(const INTEGER& rotate_count) const;\n"
328 "%s operator>>=(int rotate_count) const;\n"
329 "%s operator>>=(const INTEGER& rotate_count) const;\n\n",
330 name
, name
, name
, name
);
331 src
= mputprintf(src
,
332 "%s %s::operator<<=(int rotate_count) const\n"
334 "return *this >>= (-rotate_count);\n"
336 "%s %s::operator<<=(const INTEGER& rotate_count) const\n"
338 "rotate_count.must_bound(\""
339 "Unbound integer operand of rotate left operator.\");\n"
340 "return *this >>= (int)(-rotate_count);\n"
342 "%s %s::operator>>=(const INTEGER& rotate_count) const\n"
344 "rotate_count.must_bound(\""
345 "Unbound integer operand of rotate right operator.\");\n"
346 "return *this >>= (int)rotate_count;\n"
348 "%s %s::operator>>=(int rotate_count) const\n"
350 "if (val_ptr == NULL) "
351 "TTCN_error(\"Performing rotation operation on an unbound value of type "
353 "if (val_ptr->n_elements == 0) return *this;\n"
355 "if (rotate_count>=0) rc = rotate_count %% val_ptr->n_elements;\n"
356 "else rc = val_ptr->n_elements - ((-rotate_count) %% val_ptr->n_elements);\n"
357 "if (rc == 0) return *this;\n"
359 "ret_val.set_size(val_ptr->n_elements);\n"
360 "for (int i=0; i<val_ptr->n_elements; i++) {\n"
361 "if (val_ptr->value_elements[i] != NULL) {\n"
362 "ret_val.val_ptr->value_elements[(i+rc)%%val_ptr->n_elements] ="
363 "new %s(*val_ptr->value_elements[i]);\n"
368 name
, name
, name
, name
, name
, name
, name
, name
, dispname
, name
, type
);
371 def
= mputprintf(def
,
372 "%s operator+(const %s& other_value) const;\n\n", name
, name
);
373 src
= mputprintf(src
,
374 "%s %s::operator+(const %s& other_value) const\n"
376 "if (val_ptr == NULL || other_value.val_ptr == NULL) "
377 "TTCN_error(\"Unbound operand of %s concatenation.\");\n"
378 "if (val_ptr->n_elements == 0) return other_value;\n"
379 "if (other_value.val_ptr->n_elements == 0) return *this;\n"
381 "ret_val.set_size(val_ptr->n_elements+other_value.val_ptr->n_elements);\n"
382 "for (int i=0; i<val_ptr->n_elements; i++) {\n"
383 "if (val_ptr->value_elements[i] != NULL) {\n"
384 "ret_val.val_ptr->value_elements[i] = new %s(*val_ptr->value_elements[i]);\n"
387 "for (int i=0; i<other_value.val_ptr->n_elements; i++) {\n"
388 "if (other_value.val_ptr->value_elements[i] != NULL) {\n"
389 "ret_val.val_ptr->value_elements[i+val_ptr->n_elements] = "
390 "new %s(*other_value.val_ptr->value_elements[i]);\n"
394 "}\n\n", name
, name
, name
, dispname
, name
, type
, type
);
397 def
= mputprintf(def
,
398 "%s substr(int index, int returncount) const;\n\n", name
);
399 src
= mputprintf(src
,
400 "%s %s::substr(int index, int returncount) const\n"
402 "if (val_ptr == NULL) "
403 "TTCN_error(\"The first argument of substr() is an unbound value of "
405 "check_substr_arguments(val_ptr->n_elements, index, returncount, "
406 "\"%s\",\"element\");\n"
408 "ret_val.set_size(returncount);\n"
409 "for (int i=0; i<returncount; i++) {\n"
410 "if (val_ptr->value_elements[i+index] != NULL) {\n"
411 "ret_val.val_ptr->value_elements[i] = "
412 "new %s(*val_ptr->value_elements[i+index]);\n"
416 "}\n\n", name
, name
, dispname
, dispname
, name
, type
);
419 def
= mputprintf(def
,
420 "%s replace(int index, int len, const %s& repl) const;\n\n", name
, name
);
421 src
= mputprintf(src
,
422 "%s %s::replace(int index, int len, const %s& repl) const\n"
424 "if (val_ptr == NULL) "
425 "TTCN_error(\"The first argument of replace() is an unbound value of "
427 "if (repl.val_ptr == NULL) "
428 "TTCN_error(\"The fourth argument of replace() is an unbound value of "
430 "check_replace_arguments(val_ptr->n_elements, index, len, "
431 "\"%s\",\"element\");\n"
433 "ret_val.set_size(val_ptr->n_elements + repl.val_ptr->n_elements - len);\n"
434 "for (int i = 0; i < index; i++) {\n"
435 "if (val_ptr->value_elements[i] != NULL) {\n"
436 "ret_val.val_ptr->value_elements[i] = new %s(*val_ptr->value_elements[i]);\n"
439 "for (int i = 0; i < repl.val_ptr->n_elements; i++) {\n"
440 "if (repl.val_ptr->value_elements[i] != NULL) {\n"
441 "ret_val.val_ptr->value_elements[i+index] = "
442 "new %s(*repl.val_ptr->value_elements[i]);\n"
445 "for (int i = 0; i < val_ptr->n_elements - index - len; i++) {\n"
446 "if (val_ptr->value_elements[index+i+len] != NULL) {\n"
447 "ret_val.val_ptr->value_elements[index+i+repl.val_ptr->n_elements] = "
448 "new %s(*val_ptr->value_elements[index+i+len]);\n"
452 "}\n\n", name
, name
, name
, dispname
, dispname
, dispname
, name
, type
, type
, type
);
453 def
= mputprintf(def
,
454 "%s replace(int index, int len, const %s_template& repl) const;\n\n",
456 src
= mputprintf(src
,
457 "%s %s::replace(int index, int len, const %s_template& repl) const\n"
459 "if (!repl.is_value()) TTCN_error(\"The fourth argument of function "
460 "replace() is a template with non-specific value.\");\n"
461 "return replace(index, len, repl.valueof());\n"
462 "}\n\n", name
, name
, name
);
464 /* set_size function */
465 def
= mputstr(def
, "void set_size(int new_size);\n");
466 src
= mputprintf(src
, "void %s::set_size(int new_size)\n"
468 "if (new_size < 0) TTCN_error(\"Internal error: Setting a negative size "
469 "for a value of type %s.\");\n"
470 "if (val_ptr == NULL) {\n"
471 "val_ptr = new recordof_setof_struct;\n"
472 "val_ptr->ref_count = 1;\n"
473 "val_ptr->n_elements = 0;\n"
474 "val_ptr->value_elements = NULL;\n"
475 "} else if (val_ptr->ref_count > 1) {\n" /* copy-on-write */
476 "struct recordof_setof_struct *new_val_ptr = new recordof_setof_struct;\n"
477 "new_val_ptr->ref_count = 1;\n"
478 "new_val_ptr->n_elements = (new_size < val_ptr->n_elements) ? "
479 "new_size : val_ptr->n_elements;\n"
480 "new_val_ptr->value_elements = "
481 "(%s**)allocate_pointers(new_val_ptr->n_elements);\n"
482 "for (int elem_count = 0; elem_count < new_val_ptr->n_elements; "
484 "if (val_ptr->value_elements[elem_count] != NULL){\n"
485 "new_val_ptr->value_elements[elem_count] = "
486 "new %s(*(val_ptr->value_elements[elem_count]));\n"
490 "val_ptr = new_val_ptr;\n"
492 "if (new_size > val_ptr->n_elements) {\n"
493 "val_ptr->value_elements = (%s**)"
494 "reallocate_pointers((void**)val_ptr->value_elements, "
495 "val_ptr->n_elements, new_size);\n"
496 "#ifdef TITAN_MEMORY_DEBUG_SET_RECORD_OF\n"
497 "if((val_ptr->n_elements/1000)!=(new_size/1000)) "
498 "TTCN_warning(\"New size of type %s: %%d\",new_size);\n"
500 "val_ptr->n_elements = new_size;\n"
501 "} else if (new_size < val_ptr->n_elements) {\n"
502 "for (int elem_count = new_size; elem_count < val_ptr->n_elements; "
504 "if (val_ptr->value_elements[elem_count] != NULL)"
505 "delete val_ptr->value_elements[elem_count];\n"
506 "val_ptr->value_elements = (%s**)"
507 "reallocate_pointers((void**)val_ptr->value_elements, "
508 "val_ptr->n_elements, new_size);\n"
509 "val_ptr->n_elements = new_size;\n"
511 "}\n\n", name
, dispname
, type
, type
, type
, dispname
, type
);
513 /* is_bound function */
515 "inline boolean is_bound() const {return val_ptr != NULL; }\n");
517 /* is_present function */
519 "inline boolean is_present() const { return is_bound(); }\n");
521 /* is_value function */
523 "boolean is_value() const;\n");
524 src
= mputprintf(src
,
525 "boolean %s::is_value() const\n"
527 "if (val_ptr == NULL) return false;\n"
528 "for(int i = 0; i < val_ptr->n_elements; ++i) {\n"
529 "if (val_ptr->value_elements[i] == NULL || "
530 "!val_ptr->value_elements[i]->is_value()) return FALSE;\n"
535 /* sizeof operation */
537 "int size_of() const;\n"
538 "int n_elem() const { return size_of(); }\n");
539 src
= mputprintf(src
,
540 "int %s::size_of() const\n"
542 "if (val_ptr == NULL) "
543 "TTCN_error(\"Performing sizeof operation on an unbound value of type "
545 "return val_ptr->n_elements;\n"
546 "}\n\n", name
, dispname
);
548 /* lengthof operation */
549 def
= mputstr(def
, "int lengthof() const;\n");
550 src
= mputprintf(src
,
551 "int %s::lengthof() const\n"
553 "if (val_ptr == NULL) "
554 "TTCN_error(\"Performing lengthof operation on an unbound value of type "
556 "for (int my_length=val_ptr->n_elements; my_length>0; my_length--) "
557 "if (val_ptr->value_elements[my_length-1] != NULL) return my_length;\n"
559 "}\n\n", name
, dispname
);
562 def
= mputstr(def
, "void log() const;\n");
565 "void %s::log() const\n"
567 "if (val_ptr == NULL) {;\n"
568 "TTCN_Logger::log_event_unbound();\n"
571 "switch (val_ptr->n_elements) {\n"
573 "TTCN_Logger::log_event_str(\"{ }\");\n"
576 "TTCN_Logger::log_event_str(\"{ \");\n"
577 "for (int elem_count = 0; elem_count < val_ptr->n_elements; "
579 "if (elem_count > 0) TTCN_Logger::log_event_str(\", \");\n"
580 "(*this)[elem_count].log();\n"
582 "TTCN_Logger::log_event_str(\" }\");\n"
586 /* set_param function */
587 def
= mputstr(def
, "void set_param(Module_Param& param);\n");
588 src
= mputprintf(src
,
589 "void %s::set_param(Module_Param& param)\n"
591 " if (dynamic_cast<Module_Param_Name*>(param.get_id()) != NULL &&\n"
592 " param.get_id()->next_name()) {\n"
593 // Haven't reached the end of the module parameter name
594 // => the name refers to one of the elements, not to the whole record of
595 " char* param_field = param.get_id()->get_current_name();\n"
596 " if (param_field[0] < '0' || param_field[0] > '9') {\n"
597 " param.error(\"Unexpected record field name in module parameter, expected a valid\"\n"
598 " \" index for %s type `%s'\");\n"
600 " int param_index = -1;\n"
601 " sscanf(param_field, \"%%d\", ¶m_index);\n"
602 " (*this)[param_index].set_param(param);\n"
605 " param.basic_check(Module_Param::BC_VALUE|Module_Param::BC_LIST, \"%s value\");\n"
606 " switch (param.get_operation_type()) {\n"
607 " case Module_Param::OT_ASSIGN:\n"
608 " if (param.get_type()==Module_Param::MP_Value_List && param.get_size()==0) {\n"
609 " *this = NULL_VALUE;\n"
612 " switch (param.get_type()) {\n"
613 " case Module_Param::MP_Value_List:\n"
614 " set_size(param.get_size());\n"
615 " for (size_t i=0; i<param.get_size(); ++i) {\n"
616 " Module_Param* const curr = param.get_elem(i);\n"
617 " if (curr->get_type()!=Module_Param::MP_NotUsed) {\n"
618 " (*this)[i].set_param(*curr);\n"
622 " case Module_Param::MP_Indexed_List:\n"
623 " for (size_t i=0; i<param.get_size(); ++i) {\n"
624 " Module_Param* const curr = param.get_elem(i);\n"
625 " (*this)[curr->get_id()->get_index()].set_param(*curr);\n"
629 " param.type_error(\"%s value\", \"%s\");\n"
632 " case Module_Param::OT_CONCAT:\n"
633 " switch (param.get_type()) {\n"
634 " case Module_Param::MP_Value_List: {\n"
635 " if (!is_bound()) *this = NULL_VALUE;\n"
636 " int start_idx = lengthof();\n"
637 " for (size_t i=0; i<param.get_size(); ++i) {\n"
638 " Module_Param* const curr = param.get_elem(i);\n"
639 " if ((curr->get_type()!=Module_Param::MP_NotUsed)) {\n"
640 " (*this)[start_idx+(int)i].set_param(*curr);\n"
644 " case Module_Param::MP_Indexed_List:\n"
645 " param.error(\"Cannot concatenate an indexed value list\");\n"
648 " param.type_error(\"%s value\", \"%s\");\n"
652 " TTCN_error(\"Internal error: Unknown operation type.\");\n"
654 "}\n", name
, sdef
->kind
== RECORD_OF
? "record of" : "set of",
655 dispname
, sdef
->kind
== RECORD_OF
? "record of" : "set of",
656 sdef
->kind
== RECORD_OF
? "record of" : "set of", dispname
,
657 sdef
->kind
== RECORD_OF
? "record of" : "set of", dispname
);
659 /* set implicit omit function, recursive */
660 def
= mputstr(def
, " void set_implicit_omit();\n");
661 src
= mputprintf(src
,
662 "void %s::set_implicit_omit()\n{\n"
663 "if (val_ptr == NULL) return;\n"
664 "for (int i = 0; i < val_ptr->n_elements; i++) {\n"
665 "if (val_ptr->value_elements[i] != NULL) val_ptr->value_elements[i]->set_implicit_omit();\n"
668 /* encoding / decoding functions */
669 def
= mputstr(def
, "void encode_text(Text_Buf& text_buf) const;\n");
670 src
= mputprintf(src
,
671 "void %s::encode_text(Text_Buf& text_buf) const\n"
673 "if (val_ptr == NULL) "
674 "TTCN_error(\"Text encoder: Encoding an unbound value of type %s.\");\n"
675 "text_buf.push_int(val_ptr->n_elements);\n"
676 "for (int elem_count = 0; elem_count < val_ptr->n_elements; "
678 "(*this)[elem_count].encode_text(text_buf);\n"
679 "}\n\n", name
, dispname
);
681 def
= mputstr(def
, "void decode_text(Text_Buf& text_buf);\n");
682 src
= mputprintf(src
,
683 "void %s::decode_text(Text_Buf& text_buf)\n"
686 "val_ptr = new recordof_setof_struct;\n"
687 "val_ptr->ref_count = 1;\n"
688 "val_ptr->n_elements = text_buf.pull_int().get_val();\n"
689 "if (val_ptr->n_elements < 0) TTCN_error(\"Text decoder: Negative size "
690 "was received for a value of type %s.\");\n"
691 "val_ptr->value_elements = (%s**)allocate_pointers(val_ptr->n_elements);\n"
692 "for (int elem_count = 0; elem_count < val_ptr->n_elements; "
694 "val_ptr->value_elements[elem_count] = new %s;\n"
695 "val_ptr->value_elements[elem_count]->decode_text(text_buf);\n"
697 "}\n\n", name
, dispname
, type
, type
);
699 if(ber_needed
|| raw_needed
|| text_needed
|| xer_needed
|| json_needed
)
700 def_encdec(name
, &def
, &src
, ber_needed
, raw_needed
, text_needed
,
701 xer_needed
, json_needed
, FALSE
);
705 "int %s::TEXT_encode(const TTCN_Typedescriptor_t& p_td,"
706 " TTCN_Buffer& p_buf) const{\n"
707 " int encoded_length=0;\n"
708 " if(p_td.text->begin_encode){\n"
709 " p_buf.put_cs(*p_td.text->begin_encode);\n"
710 " encoded_length+=p_td.text->begin_encode->lengthof();\n"
712 " if(val_ptr==NULL) {\n"
713 " TTCN_EncDec_ErrorContext::error\n"
714 " (TTCN_EncDec::ET_UNBOUND, \"Encoding an unbound value.\");\n"
715 " if(p_td.text->end_encode){\n"
716 " p_buf.put_cs(*p_td.text->end_encode);\n"
717 " encoded_length+=p_td.text->end_encode->lengthof();\n"
719 " return encoded_length;\n"
721 " for(int a=0;a<val_ptr->n_elements;a++){\n"
722 " if(a!=0 && p_td.text->separator_encode){\n"
723 " p_buf.put_cs(*p_td.text->separator_encode);\n"
724 " encoded_length+=p_td.text->separator_encode->lengthof();\n"
726 " encoded_length+=(*this)[a].TEXT_encode(%s_descr_,p_buf);\n"
728 " if(p_td.text->end_encode){\n"
729 " p_buf.put_cs(*p_td.text->end_encode);\n"
730 " encoded_length+=p_td.text->end_encode->lengthof();\n"
732 " return encoded_length;\n"
734 ,name
,sdef
->oftypedescrname
736 src
= mputprintf(src
,
737 "int %s::TEXT_decode(const TTCN_Typedescriptor_t& p_td,"
738 " TTCN_Buffer& p_buf, Limit_Token_List& limit, boolean no_err"
739 ", boolean first_call){\n"
740 " int decoded_length=0;\n"
741 " size_t pos=p_buf.get_pos();\n"
742 " boolean sep_found=FALSE;\n"
743 " int sep_length=0;\n"
745 " if(p_td.text->begin_decode){\n"
747 " if((tl=p_td.text->begin_decode->match_begin(p_buf))<0){\n"
748 " if(no_err)return -1;\n"
749 " TTCN_EncDec_ErrorContext::error\n"
750 " (TTCN_EncDec::ET_TOKEN_ERR, \"The specified token '%%s'"
751 " not found for '%%s': \",(const char*)*(p_td.text->begin_decode)"
755 " decoded_length+=tl;\n"
756 " p_buf.increase_pos(tl);\n"
758 " if(p_td.text->end_decode){\n"
759 " limit.add_token(p_td.text->end_decode);\n"
762 " if(p_td.text->separator_decode){\n"
763 " limit.add_token(p_td.text->separator_decode);\n"
766 " if(first_call) {\n"
768 " val_ptr=new recordof_setof_struct;\n"
769 " val_ptr->ref_count=1;\n"
770 " val_ptr->n_elements=0;\n"
771 " val_ptr->value_elements=NULL;\n"
773 " int more=val_ptr->n_elements;\n"
776 " pos=p_buf.get_pos();\n"
777 " int len=val->TEXT_decode(%s_descr_,p_buf,limit,TRUE);\n"
778 " if(len==-1 || (len==0 && !limit.has_token())){\n"
779 " p_buf.set_pos(pos);\n"
782 " p_buf.set_pos(p_buf.get_pos()-sep_length);\n"
783 " decoded_length-=sep_length;\n"
787 " sep_found=FALSE;\n"
788 " val_ptr->value_elements = (%s**)reallocate_pointers"
789 "((void**)val_ptr->value_elements, val_ptr->n_elements, "
790 "val_ptr->n_elements + 1);\n"
791 " val_ptr->value_elements[val_ptr->n_elements]=val;\n"
792 " val_ptr->n_elements++;\n"
793 " decoded_length+=len;\n"
794 " if(p_td.text->separator_decode){\n"
796 " if((tl=p_td.text->separator_decode->match_begin(p_buf))<0){\n"
799 " decoded_length+=tl;\n"
800 " p_buf.increase_pos(tl);\n"
803 " } else if(p_td.text->end_decode){\n"
805 " if((tl=p_td.text->end_decode->match_begin(p_buf))!=-1){\n"
806 " decoded_length+=tl;\n"
807 " p_buf.increase_pos(tl);\n"
808 " limit.remove_tokens(ml);\n"
809 " return decoded_length;\n"
811 " } else if(limit.has_token(ml)){\n"
813 " if((tl=limit.match(p_buf,ml))==0){\n"
814 " sep_found=FALSE;\n"
819 ,name
,type
,type
,sdef
->oftypedescrname
,type
822 " limit.remove_tokens(ml);\n"
823 " if(p_td.text->end_decode){\n"
825 " if((tl=p_td.text->end_decode->match_begin(p_buf))<0){\n"
827 " if(!first_call){\n"
828 " for(int a=more; a<val_ptr->n_elements; a++) "
829 "delete val_ptr->value_elements[a];\n"
830 " val_ptr->n_elements=more;\n"
834 " TTCN_EncDec_ErrorContext::error"
835 "(TTCN_EncDec::ET_TOKEN_ERR, \"The specified token '%s'"
836 " not found for '%s': \",(const char*)*(p_td.text->end_decode)"
838 " return decoded_length;\n"
840 " decoded_length+=tl;\n"
841 " p_buf.increase_pos(tl);\n"
843 " if(val_ptr->n_elements==0){\n"
844 " if(!(p_td.text->end_decode || p_td.text->begin_decode)) {\n"
845 " if(no_err)return -1;\n"
846 " TTCN_EncDec_ErrorContext::error"
847 "(TTCN_EncDec::ET_TOKEN_ERR, \"No record/set of member found.\");\n"
848 " return decoded_length;\n"
851 " if(!first_call && more==val_ptr->n_elements && "
852 "!(p_td.text->end_decode || p_td.text->begin_decode)) return -1;\n"
853 " return decoded_length;\n"
860 /* BER_encode_TLV() */
863 "ASN_BER_TLV_t* %s::BER_encode_TLV(const TTCN_Typedescriptor_t&"
864 " p_td, unsigned p_coding) const\n"
866 " BER_chk_descr(p_td);\n"
867 " ASN_BER_TLV_t *new_tlv=BER_encode_chk_bound(is_bound());\n"
869 " new_tlv=ASN_BER_TLV_t::construct(NULL);\n"
870 " TTCN_EncDec_ErrorContext ec;\n"
871 " for(int elem_i=0; elem_i<val_ptr->n_elements; elem_i++) {\n"
872 " ec.set_msg(\"Component #%%d: \", elem_i);\n"
873 " new_tlv->add_TLV((*this)[elem_i].BER_encode_TLV"
874 "(%s_descr_, p_coding));\n"
878 " new_tlv=ASN_BER_V2TLV(new_tlv, p_td, p_coding);\n"
882 /* BER_decode_TLV() */
883 "boolean %s::BER_decode_TLV(const TTCN_Typedescriptor_t& p_td,"
884 " const ASN_BER_TLV_t& p_tlv, unsigned L_form)\n"
886 " BER_chk_descr(p_td);\n"
887 " ASN_BER_TLV_t stripped_tlv;\n"
888 " BER_decode_strip_tags(*p_td.ber, p_tlv, L_form, stripped_tlv);\n"
889 " TTCN_EncDec_ErrorContext ec_0(\"While decoding '%%s' type: \","
891 " stripped_tlv.chk_constructed_flag(TRUE);\n"
893 " val_ptr = new recordof_setof_struct;\n"
894 " val_ptr->ref_count = 1;\n"
895 " val_ptr->n_elements = 0;\n"
896 " val_ptr->value_elements = NULL;\n"
898 " ASN_BER_TLV_t tmp_tlv;\n"
899 " TTCN_EncDec_ErrorContext ec_1(\"Component #\");\n"
900 " TTCN_EncDec_ErrorContext ec_2(\"0: \");\n"
901 " while(BER_decode_constdTLV_next(stripped_tlv, V_pos, L_form, "
903 " val_ptr->value_elements = (%s**)reallocate_pointers("
904 "(void**)val_ptr->value_elements, val_ptr->n_elements, "
905 "val_ptr->n_elements + 1);\n"
906 " val_ptr->n_elements++;\n"
907 " val_ptr->value_elements[val_ptr->n_elements - 1] = new %s;\n"
908 " val_ptr->value_elements[val_ptr->n_elements - 1]->BER_decode_TLV(%s_descr_, tmp_tlv, "
910 " ec_2.set_msg(\"%%d: \", val_ptr->n_elements);\n"
915 , name
, sdef
->oftypedescrname
916 , sdef
->kind
==SET_OF
?" new_tlv->sort_tlvs();\n":""
917 , name
, type
, type
, sdef
->oftypedescrname
920 if(sdef
->has_opentypes
) {
921 /* BER_decode_opentypes() */
924 "void BER_decode_opentypes(TTCN_Type_list& p_typelist,"
925 " unsigned L_form);\n");
928 "void %s::BER_decode_opentypes(TTCN_Type_list& p_typelist,"
929 " unsigned L_form)\n"
931 " p_typelist.push(this);\n"
932 " TTCN_EncDec_ErrorContext ec_0(\"Component #\");\n"
933 " TTCN_EncDec_ErrorContext ec_1;\n"
934 " for(int elem_i=0; elem_i<val_ptr->n_elements; elem_i++) {\n"
935 " ec_1.set_msg(\"%%d: \", elem_i);\n"
936 " val_ptr->value_elements[elem_i]->BER_decode_opentypes(p_typelist,"
939 " p_typelist.pop();\n"
949 "int %s::RAW_decode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf, "
950 "int limit, raw_order_t top_bit_ord, boolean /*no_err*/, int sel_field"
951 ", boolean first_call){\n"
952 " int prepaddlength=p_buf.increase_pos_padd(p_td.raw->prepadding);\n"
953 " limit-=prepaddlength;\n"
954 " int decoded_length=0;\n"
955 " int decoded_field_length=0;\n"
956 " size_t start_of_field=0;\n"
957 " if(first_call) {\n"
959 " val_ptr=new recordof_setof_struct;\n"
960 " val_ptr->ref_count=1;\n"
961 " val_ptr->n_elements=0;\n"
962 " val_ptr->value_elements=NULL;\n"
964 " int start_field=val_ptr->n_elements;\n"
965 " if(p_td.raw->fieldlength || sel_field!=-1){\n"
967 " if(sel_field==-1) sel_field=p_td.raw->fieldlength;\n"
968 " for(a=0;a<sel_field;a++){\n"
969 " decoded_field_length=(*this)[a+start_field].RAW_decode(%s_descr_,"
970 "p_buf,limit,top_bit_ord,TRUE);\n"
971 " if(decoded_field_length < 0) return decoded_field_length;\n"
972 " decoded_length+=decoded_field_length;\n"
973 " limit-=decoded_field_length;\n"
975 " if(a==0) val_ptr->n_elements=0;\n"
977 " int a=start_field;\n"
979 " if(!first_call) return -1;\n"
980 " val_ptr->n_elements=0;\n"
981 " return decoded_length+p_buf.increase_pos_padd(p_td.raw->padding)"
985 " start_of_field=p_buf.get_pos_bit();\n"
986 " decoded_field_length=(*this)[a].RAW_decode(%s_descr_,p_buf,limit,"
987 "top_bit_ord,TRUE);\n"
988 " if(decoded_field_length < 0){\n"
989 " delete &(*this)[a];\n"
990 " val_ptr->n_elements--;\n"
991 " p_buf.set_pos_bit(start_of_field);\n"
992 " if(a>start_field){\n"
993 " return decoded_length+p_buf.increase_pos_padd(p_td.raw->padding)"
995 " } else return -1;\n"
997 " decoded_length+=decoded_field_length;\n"
998 " limit-=decoded_field_length;\n"
1000 ,name
,sdef
->oftypedescrname
,sdef
->oftypedescrname
1002 if(sdef
->raw
.extension_bit
!=XDEFNO
&& sdef
->raw
.extension_bit
!=XDEFDEFAULT
){
1004 " if (%sp_buf.get_last_bit())\n"
1005 " return decoded_length+p_buf.increase_pos_padd(p_td.raw->padding)"
1006 "+prepaddlength;\n", sdef
->raw
.extension_bit
== XDEFYES
? "" : "!");
1011 " return decoded_length+p_buf.increase_pos_padd(p_td.raw->padding)"
1014 "int %s::RAW_encode(const TTCN_Typedescriptor_t& p_td,"
1015 "RAW_enc_tree& myleaf) const{\n"
1016 " int encoded_length=0;\n"
1017 " int encoded_num_of_records=p_td.raw->fieldlength?"
1018 "smaller(val_ptr->n_elements, p_td.raw->fieldlength)"
1019 ":val_ptr->n_elements;\n"
1020 " myleaf.isleaf=FALSE;\n"
1021 " myleaf.rec_of=TRUE;\n"
1022 " myleaf.body.node.num_of_nodes=encoded_num_of_records;\n"
1023 " myleaf.body.node.nodes=init_nodes_of_enc_tree(encoded_num_of_records);\n"
1024 " for(int a=0;a<encoded_num_of_records;a++){\n"
1025 " myleaf.body.node.nodes[a]=new RAW_enc_tree(TRUE,&myleaf,"
1026 "&(myleaf.curr_pos),a,%s_descr_.raw);\n"
1027 " encoded_length+=(*this)[a].RAW_encode(%s_descr_,"
1028 "*myleaf.body.node.nodes[a]);\n"
1030 " return myleaf.length=encoded_length;\n}\n\n"
1031 , name
, sdef
->oftypedescrname
, sdef
->oftypedescrname
1035 if (xer_needed
) { /* XERSTUFF encoder codegen for record-of, RT1 */
1037 "char **collect_ns(const XERdescriptor_t& p_td, size_t& num, bool& def_ns) const;\n");
1039 /* Write the body of the XER encoder/decoder functions. The declaration
1040 * is written by def_encdec() in encdec.c */
1041 src
= mputprintf(src
,
1042 "boolean %s::can_start(const char *name, const char *uri, "
1043 "XERdescriptor_t const& xd, unsigned int flavor) {\n"
1044 " boolean e_xer = is_exer(flavor);\n"
1045 " if (e_xer && (xd.xer_bits & ANY_ELEMENT)) "
1048 if (sdef
->nFollowers
) {
1049 /* If there are optional fields following the record-of, then seeing
1050 * {any XML tag that belongs to those fields} where the record-of may be
1051 * means that the record-of is empty. */
1053 src
= mputstr(src
, "{\n");
1054 for (f
= 0; f
< sdef
->nFollowers
; ++f
) {
1055 src
= mputprintf(src
,
1056 " if (%s::can_start(name, uri, %s_xer_, flavor)) return FALSE;\n"
1057 , sdef
->followers
[f
].type
1058 , sdef
->followers
[f
].typegen
1065 else src
= mputstr(src
, "return TRUE;\n");
1067 src
= mputprintf(src
,
1068 " if ((!e_xer || !(xd.xer_bits & UNTAGGED)) && !(flavor & XER_RECOF)) return "
1069 "check_name(name, xd, e_xer) && (!e_xer || check_namespace(uri, xd));\n"
1070 " else return %s::can_start(name, uri, %s_xer_, flavor | XER_RECOF);\n"
1073 , sdef
->oftypedescrname
1076 src
= mputprintf(src
,
1077 "char ** %s::collect_ns(const XERdescriptor_t& p_td, size_t& num, bool& def_ns) const {\n"
1078 " size_t num_collected;\n"
1079 " char **collected_ns = Base_Type::collect_ns(p_td, num_collected, def_ns);\n"
1080 /* The above may throw but then nothing was allocated. */
1081 " if (val_ptr) try {\n"
1083 " size_t num_new;\n"
1084 " for (int i = 0; i < val_ptr->n_elements; ++i) {\n"
1085 " bool def_ns_1 = false;"
1086 " new_ns = (*this)[i].collect_ns(%s_xer_, num_new, def_ns_1);\n"
1087 " merge_ns(collected_ns, num_collected, new_ns, num_new);\n"
1088 " def_ns = def_ns || def_ns_1;\n" /* alas, no ||= */
1092 /* Probably a TC_Error thrown from elements[i]->collect_ns() if e.g.
1093 * encoding an unbound value. */
1094 " while (num_collected > 0) Free(collected_ns[--num_collected]);\n"
1095 " Free(collected_ns);\n"
1098 " num = num_collected;\n"
1099 " return collected_ns;\n"
1101 , name
, sdef
->oftypedescrname
);
1104 "int %s::XER_encode(const XERdescriptor_t& p_td, TTCN_Buffer& p_buf, "
1105 "unsigned int p_flavor, int p_indent, embed_values_enc_struct_t* emb_val) const\n{\n"
1106 " if (val_ptr == 0) TTCN_error(\"Attempt to XER-encode an unbound record of\");\n" /* TODO type name */
1107 " int encoded_length=(int)p_buf.get_len();\n"
1108 " boolean e_xer = is_exer(p_flavor);\n"
1109 " boolean own_tag = !(e_xer && p_indent && ((p_td.xer_bits & (ANY_ELEMENT|ANY_ATTRIBUTES|UNTAGGED))\n"
1110 " || (p_flavor & USE_TYPE_ATTR)));\n"
1111 " boolean indenting = !is_canonical(p_flavor) && own_tag;\n"
1112 "%s" /* Factor out p_indent if not attribute */
1113 " if (val_ptr->n_elements==0) {\n" /* Empty record of */
1115 , sdef
->xerAttribute
? "" : " if (indenting) do_indent(p_buf, p_indent);\n"
1117 if (sdef
->xerAttribute
) {
1119 " if (e_xer) {\n" /* Empty attribute. */
1120 " begin_attribute(p_td, p_buf);\n"
1121 " p_buf.put_c('\\'');\n"
1129 " {\n" /* Do empty element tag */
1131 " p_buf.put_c('<');\n"
1132 " if (e_xer) write_ns_prefix(p_td, p_buf);\n"
1133 " p_buf.put_s((size_t)p_td.namelens[e_xer]-2, (const unsigned char*)p_td.names[e_xer]);\n"
1134 /* namespace declarations for the toplevel element */
1135 " if (e_xer && p_indent==0)\n"
1137 " size_t num_collected = 0;\n"
1138 " char **collected_ns = NULL;\n"
1139 " bool def_ns = false;\n"
1140 " collected_ns = collect_ns(p_td, num_collected, def_ns);\n"
1141 " for (size_t cur_coll = 0; cur_coll < num_collected; ++cur_coll) {\n"
1142 " p_buf.put_s(strlen(collected_ns[cur_coll]), (cbyte*)collected_ns[cur_coll]);\n"
1143 " Free(collected_ns[cur_coll]);\n"
1145 " Free(collected_ns);\n"
1148 " p_buf.put_s(2 + indenting, (const unsigned char*)\"/>\\n\");\n"
1151 " else {\n" /* Not empty record of. Start tag or attribute */
1152 , sdef
->xerAttribute
? " if (indenting) do_indent(p_buf, p_indent);\n" : ""
1154 if (sdef
->xerAnyAttrElem
) {
1156 " if (e_xer && (p_td.xer_bits & ANY_ATTRIBUTES)) {\n"
1157 " static const universal_char sp = { 0,0,0,' ' };\n"
1158 " static const universal_char tb = { 0,0,0,9 };\n"
1159 " size_t buf_len = p_buf.get_len(), shorter = 0;\n"
1160 " const unsigned char * const buf_data = p_buf.get_data();\n"
1161 " if (buf_data[buf_len - 1 - shorter] == '\\n') ++shorter;\n"
1162 " if (buf_data[buf_len - 1 - shorter] == '>' ) ++shorter;\n"
1163 " unsigned char saved[4];\n"
1164 " memcpy(saved, buf_data + (buf_len - shorter), shorter);\n"
1165 " p_buf.increase_length(-shorter);\n"
1166 " for (int i = 0; i < val_ptr->n_elements; ++i) {\n"
1167 " TTCN_EncDec_ErrorContext ec_0(\"Attribute %d: \", i);\n"
1168 " if (val_ptr->value_elements[i] == NULL) {\n"
1169 " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND,\n"
1170 " \"Encoding an unbound universal charstring value.\");\n"
1173 " size_t len = val_ptr->value_elements[i]->lengthof();\n"
1175 " const UNIVERSAL_CHARSTRING_ELEMENT& ue = (*val_ptr->value_elements[i])[len - 1];\n"
1176 " if (sp == ue || tb == ue) --len;\n"
1179 " size_t j, sp_at = 0;\n"
1180 /* Find the "separators" in each string */
1181 " for (j = 0; j < len; j++) {\n"
1182 " UNIVERSAL_CHARSTRING_ELEMENT ue = (*val_ptr->value_elements[i])[j];\n"
1184 " if (sp == ue || tb == ue) {}\n"
1187 " if (sp == ue || tb == ue) sp_at = j;\n"
1190 " size_t buf_start = p_buf.get_len();\n"
1191 /* Now write them */
1192 " if (sp_at > 0) {\n"
1193 " char * ns = mprintf(\" xmlns:b%d='\", i);\n"
1194 " size_t ns_len = mstrlen(ns);\n"
1195 " p_buf.put_s(ns_len, (const unsigned char*)ns);\n"
1197 " UNIVERSAL_CHARSTRING before(sp_at, (const universal_char*)(*val_ptr->value_elements[i]));\n"
1198 " before.XER_encode(UNIVERSAL_CHARSTRING_xer_, p_buf, p_flavor | ANY_ATTRIBUTES, p_indent, 0);\n"
1199 // Ensure the namespace abides to its restrictions
1200 " if (p_td.xer_bits & (ANY_FROM | ANY_EXCEPT)) {\n"
1201 " TTCN_Buffer ns_buf;\n"
1202 " before.encode_utf8(ns_buf);\n"
1204 " ns_buf.get_string(cs);\n"
1205 " check_namespace_restrictions(p_td, (const char*)cs);\n"
1208 " p_buf.put_c('\\'');\n"
1209 " p_buf.put_c(' ');\n"
1211 /* Keep just the "b%d" part from ns */
1212 " p_buf.put_s(ns_len - 9, (const unsigned char*)ns + 7);\n"
1213 " p_buf.put_c(':');\n"
1217 " p_buf.put_c(' ');\n"
1219 // Make sure the unqualified namespace is allowed
1220 " if (p_td.xer_bits & (ANY_FROM | ANY_EXCEPT)) {\n"
1221 " check_namespace_restrictions(p_td, NULL);\n"
1225 " UNIVERSAL_CHARSTRING after(len - j, (const universal_char*)(*val_ptr->value_elements[i]) + j);\n"
1226 " after.XER_encode(UNIVERSAL_CHARSTRING_xer_, p_buf, p_flavor | ANY_ATTRIBUTES, p_indent, 0);\n"
1227 // Put this attribute in a dummy element and walk through it to check its validity
1228 " TTCN_Buffer check_buf;\n"
1229 " check_buf.put_s(2, (unsigned char*)\"<a\");\n"
1230 " check_buf.put_s(p_buf.get_len() - buf_start, p_buf.get_data() + buf_start);\n"
1231 " check_buf.put_s(2, (unsigned char*)\"/>\");"
1232 " XmlReaderWrap checker(check_buf);\n"
1233 " while (1 == checker.Read()) ;\n"
1236 " p_buf.put_s(shorter, saved);\n" /* restore the '>' and anything after */
1239 if (sdef
->xerAttribute
) {
1242 " begin_attribute(p_td, p_buf);\n"
1248 " p_buf.put_c('<');\n"
1249 " boolean write_ns = (e_xer && p_indent==0);\n"
1250 " boolean keep_newline = (indenting && !(e_xer && (p_td.xer_bits & XER_LIST)));\n"
1251 " if (e_xer) write_ns_prefix(p_td, p_buf);\n"
1252 " p_buf.put_s((size_t)p_td.namelens[e_xer]-write_ns-(write_ns || !keep_newline), "
1253 "(const unsigned char*)p_td.names[e_xer]);\n"
1255 /* namespace declarations for the toplevel element */
1256 " if (e_xer && p_indent==0)\n"
1258 " size_t num_collected = 0;\n"
1259 " char **collected_ns = NULL;\n"
1260 " bool def_ns = false;\n"
1261 " collected_ns = collect_ns(p_td, num_collected, def_ns);\n"
1262 " for (size_t cur_coll = 0; cur_coll < num_collected; ++cur_coll) {\n"
1263 " p_buf.put_s(strlen(collected_ns[cur_coll]), (cbyte*)collected_ns[cur_coll]);\n"
1264 " Free(collected_ns[cur_coll]);\n"
1266 " Free(collected_ns);\n"
1267 " p_buf.put_s(1 + keep_newline, (cbyte*)\">\\n\");\n"
1269 , sdef
->xerAttribute
? " if (indenting) do_indent(p_buf, p_indent);\n" : ""
1271 if (sdef
->xmlValueList
) {
1272 src
=mputstr(src
, " if (indenting && !e_xer) do_indent(p_buf, p_indent+1);\n"); /* !e_xer or GDMO */
1276 " p_flavor |= XER_RECOF | (p_td.xer_bits & XER_LIST);\n"
1277 " TTCN_EncDec_ErrorContext ec_0(\"Index \");\n"
1278 " TTCN_EncDec_ErrorContext ec_1;\n"
1281 " for (int i = 0; i < val_ptr->n_elements; ++i) {\n"
1282 /*" if (i > 0 && !own_tag && 0 != emb_val &&\n"
1283 " emb_val->embval_index < emb_val->embval_size) {\n"
1284 " emb_val->embval_array->get_embedded_value(emb_val->embval_index).XER_encode(\n"
1285 " UNIVERSAL_CHARSTRING_xer_, p_buf, p_flavor | EMBED_VALUES, p_indent+1, 0);\n"
1286 " ++emb_val->embval_index;\n"
1287 " }\n" - temporarily removed in RT1 */
1288 " ec_1.set_msg(\"%%d: \", i);\n"
1289 " if (e_xer && (p_td.xer_bits & XER_LIST) && i>0) p_buf.put_c(' ');\n"
1290 " (*this)[i].XER_encode(%s_xer_, p_buf, p_flavor, p_indent+own_tag, emb_val);\n"
1292 " if (indenting && !is_exerlist(p_flavor)) {\n",
1293 sdef
->oftypedescrname
1295 if (sdef
->xmlValueList
) {
1296 src
=mputstr(src
, " if (!e_xer) p_buf.put_c('\\n');\n"); /* !e_xer or GDMO */
1299 " do_indent(p_buf, p_indent);\n"
1301 if (sdef
->xerAttribute
) {
1303 " if (e_xer) p_buf.put_c('\\'');\n"
1308 " p_buf.put_c('<');\n"
1309 " p_buf.put_c('/');\n"
1310 " if (e_xer) write_ns_prefix(p_td, p_buf);\n"
1311 " p_buf.put_s((size_t)p_td.namelens[e_xer]-!indenting, (const unsigned char*)p_td.names[e_xer]);\n"
1313 if (sdef
->xerAnyAttrElem
) {
1314 src
= mputstr(src
, " }\n");
1317 " }\n" /* end if(no elements) */
1318 " return (int)p_buf.get_len() - encoded_length;\n"
1322 src
= mputprintf(src
, /* XERSTUFF decoder codegen for record-of */
1324 "// written by %s in " __FILE__
" at %d\n"
1326 "int %s::XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& p_reader, "
1327 "unsigned int p_flavor, embed_values_dec_struct_t* emb_val)\n{\n"
1328 " boolean e_xer = is_exer(p_flavor);\n"
1329 " int xerbits = p_td.xer_bits;\n"
1330 " if (p_flavor & XER_TOPLEVEL) xerbits &= ~UNTAGGED;\n"
1331 " boolean own_tag = !(e_xer && ((xerbits & (ANY_ELEMENT|ANY_ATTRIBUTES|UNTAGGED))\n"
1332 " || (p_flavor & USE_TYPE_ATTR)));\n" /* incase the parent has USE-UNION */
1333 /* not toplevel anymore and remove the flags for USE-UNION the oftype doesn't need them */
1334 " p_flavor &= ~XER_TOPLEVEL & ~XER_LIST & ~USE_TYPE_ATTR;\n"
1335 " int rd_ok=1, xml_depth=-1;\n"
1336 " *this = NULL_VALUE;\n" /* empty but initialized array */
1337 " int type = 0;\n" /* none */
1338 " if (own_tag) for (rd_ok = p_reader.Ok(); rd_ok == 1; rd_ok = p_reader.Read()) {\n"
1339 " type = p_reader.NodeType();\n"
1340 " if (e_xer && (p_td.xer_bits & XER_ATTRIBUTE)) {\n"
1341 " if ((XML_READER_TYPE_ELEMENT == type && p_reader.MoveToFirstAttribute() == 1)\n"
1342 " || XML_READER_TYPE_ATTRIBUTE == type) {\n"
1343 " verify_name(p_reader, p_td, e_xer);\n"
1347 " if (e_xer && (p_td.xer_bits & XER_LIST)) {\n"
1348 " if (XML_READER_TYPE_TEXT == type) break;\n"
1351 " if (XML_READER_TYPE_ELEMENT == type) {\n"
1352 " verify_name(p_reader, p_td, e_xer);\n"
1353 " xml_depth = p_reader.Depth();\n"
1356 " }\n" /* endif(e_xer && list) */
1357 " }\n" /* next read */
1358 " else xml_depth = p_reader.Depth();\n"
1359 " p_flavor |= XER_RECOF;\n"
1361 , __FUNCTION__
, __LINE__
1366 src
= mputprintf(src
,
1367 " if (e_xer && (p_td.xer_bits & XER_LIST)) {\n" /* LIST decoding*/
1368 " char *x_val = (char*)p_reader.NewValue();\n" /* we own it */
1369 " size_t x_pos = 0;\n"
1370 " size_t x_len = strlen(x_val);\n"
1371 /* The string contains a bunch of values separated by whitespace.
1372 * Tokenize the string and create a new buffer which looks like
1373 * an XML element (<ns:name xmlns:ns='uri'>value</ns:name>),
1374 * then use that to decode the value. */
1375 " for(char * str = strtok(x_val, \" \\t\\x0A\\x0D\"); str != 0; str = strtok(x_val + x_pos, \" \\t\\x0A\\x0D\")) {\n"
1376 // Calling strtok with NULL won't work here, since the decoded element can have strtok calls aswell
1377 " x_pos += strlen(str) + 1;\n"
1378 " TTCN_Buffer buf_2;\n"
1379 " buf_2.put_c('<');\n"
1380 " write_ns_prefix(%s_xer_, buf_2);\n"
1381 " const char * const exer_name = %s_xer_.names[1];\n"
1382 " boolean i_can_has_ns = %s_xer_.my_module != 0 && %s_xer_.ns_index != -1;\n"
1383 /* If it has a namespace, chop off the '>' from the end */
1384 " buf_2.put_s((size_t)%s_xer_.namelens[1]-1-i_can_has_ns, (cbyte*)exer_name);\n"
1385 " if (i_can_has_ns) {\n"
1386 " const namespace_t * const pns = %s_xer_.my_module->get_ns(%s_xer_.ns_index);\n"
1387 " buf_2.put_s(7 - (*pns->px == 0), (cbyte*)\" xmlns:\");\n"
1388 " buf_2.put_s(strlen(pns->px), (cbyte*)pns->px);\n"
1389 " buf_2.put_s(2, (cbyte*)\"='\");\n"
1390 " buf_2.put_s(strlen(pns->ns), (cbyte*)pns->ns);\n"
1391 " buf_2.put_s(2, (cbyte*)\"'>\");\n"
1393 /* start tag completed */
1394 " buf_2.put_s(strlen(str), (cbyte*)str);\n"
1395 " buf_2.put_c('<');\n"
1396 " buf_2.put_c('/');\n"
1397 " write_ns_prefix(%s_xer_, buf_2);\n"
1398 " buf_2.put_s((size_t)%s_xer_.namelens[1], (cbyte*)exer_name);\n"
1399 " XmlReaderWrap reader_2(buf_2);\n"
1400 " rd_ok = reader_2.Read();\n" /* Move to the start element. */
1401 /* Don't move to the #text, that's the callee's responsibility. */
1402 /* The call to the non-const operator[] creates a new element object,
1403 * then we call its XER_decode with the temporary XML reader. */
1404 " (*this)[val_ptr->n_elements].XER_decode(%s_xer_, reader_2, p_flavor, 0);\n"
1405 " if (p_flavor & EXIT_ON_ERROR && !(*this)[val_ptr->n_elements - 1].is_bound()) {\n"
1406 " if (1 == val_ptr->n_elements) {\n"
1407 // Failed to decode even the first element
1410 // Some elements were successfully decoded -> only delete the last one
1411 " set_size(val_ptr->n_elements - 1);\n"
1413 " xmlFree(x_val);\n"
1416 " if (x_pos >= x_len) break;\n"
1418 " xmlFree(x_val);\n"
1419 " if ((p_td.xer_bits & XER_ATTRIBUTE)) ;\n"
1420 /* Let the caller do AdvanceAttribute() */
1421 " else if (own_tag) {\n"
1422 " p_reader.Read();\n" /* on closing tag */
1423 " p_reader.Read();\n" /* past it */
1426 , sdef
->oftypedescrname
, sdef
->oftypedescrname
1427 , sdef
->oftypedescrname
, sdef
->oftypedescrname
1428 , sdef
->oftypedescrname
, sdef
->oftypedescrname
1429 , sdef
->oftypedescrname
, sdef
->oftypedescrname
1430 , sdef
->oftypedescrname
, sdef
->oftypedescrname
1433 src
= mputprintf(src
,
1435 " if (p_flavor & PARENT_CLOSED) ;\n"
1436 /* Nothing to do, but do not advance past the parent's element */
1437 " else if (own_tag && p_reader.IsEmptyElement()) rd_ok = p_reader.Read();\n"
1438 /* It's our XML empty element: nothing to do, skip past it */
1440 /* Note: there is no p_reader.Read() at the end of the loop below.
1441 * Each element is supposed to consume enough to leave the next element
1442 * well-positioned. */
1443 " for (rd_ok = own_tag ? p_reader.Read() : p_reader.Ok(); rd_ok == 1; ) {\n"
1444 " type = p_reader.NodeType();\n"
1445 " if (XML_READER_TYPE_ELEMENT == type)\n"
1447 if (sdef
->xerAnyAttrElem
) {
1448 src
= mputprintf(src
,
1449 " if (e_xer && (p_td.xer_bits & ANY_ELEMENT)) {\n"
1450 /* This is a record-of with ANY-ELEMENT applied, which is really meant
1451 * for the element type (a string), so behave like a record-of
1452 * (string with ANY-ELEMENT): call the non-const operator[]
1453 * to create a new element, then read the entire XML element into it. */
1454 " (*this)[val_ptr->n_elements] = (const char*)p_reader.ReadOuterXml();\n"
1455 /* Consume the element, then move ahead */
1456 " for (rd_ok = p_reader.Read(); rd_ok == 1 && p_reader.Depth() > xml_depth; rd_ok = p_reader.Read()) {}\n"
1457 " if (p_reader.NodeType() != XML_READER_TYPE_ELEMENT) rd_ok = p_reader.Read();\n"
1460 src
= mputprintf(src
,
1462 /* An untagged record-of ends if it encounters an element with a name
1463 * that doesn't match its component */
1464 " if (!own_tag && !can_start((const char*)p_reader.LocalName(), "
1465 "(const char*)p_reader.NamespaceUri(), %s_xer_, p_flavor)) {\n"
1466 " for (; rd_ok == 1 && p_reader.Depth() > xml_depth; rd_ok = p_reader.Read()) ;\n"
1469 /* The call to the non-const operator[] creates the element */
1470 " (*this)[val_ptr->n_elements].XER_decode(%s_xer_, p_reader, p_flavor, emb_val);\n"
1471 " if (0 != emb_val && !own_tag && val_ptr->n_elements > 1) {\n"
1472 " ++emb_val->embval_index;\n"
1476 " else if (XML_READER_TYPE_END_ELEMENT == type) {\n"
1477 " for (; p_reader.Depth() > xml_depth; rd_ok = p_reader.Read()) ;\n"
1479 " verify_end(p_reader, p_td, xml_depth, e_xer);\n"
1480 " rd_ok = p_reader.Read();\n" /* move forward one last time */
1484 /*" else if (XML_READER_TYPE_TEXT == type && 0 != emb_val && !own_tag && get_nof_elements() > 0) {\n"
1485 " UNIVERSAL_CHARSTRING emb_ustr((const char*)p_reader.Value());\n"
1486 " emb_val->embval_array->set_embedded_value(emb_val->embval_index, emb_ustr);\n"
1487 " rd_ok = p_reader.Read();\n"
1488 " }\n" - temporarily removed in RT1 */
1490 " rd_ok = p_reader.Read();\n"
1492 " }\n" /* next read */
1493 " }\n" /* if not empty element */
1494 " }\n" /* if not LIST */
1497 , sdef
->oftypedescrname
, sdef
->oftypedescrname
1502 src
= mputprintf(src
,
1503 "int %s::JSON_encode(const TTCN_Typedescriptor_t&, JSON_Tokenizer& p_tok) const\n"
1505 " if (!is_bound()) {\n"
1506 " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND,\n"
1507 " \"Encoding an unbound value of type %s.\");\n"
1510 " int enc_len = p_tok.put_next_token(JSON_TOKEN_ARRAY_START, NULL);\n"
1511 " for(int i = 0; i < val_ptr->n_elements; ++i) {\n"
1512 " int ret_val = (*this)[i].JSON_encode(%s_descr_, p_tok);\n"
1513 " if (0 > ret_val) break;\n"
1514 " enc_len += ret_val;\n"
1516 " enc_len += p_tok.put_next_token(JSON_TOKEN_ARRAY_END, NULL);\n"
1517 " return enc_len;\n"
1519 , name
, dispname
, sdef
->oftypedescrname
);
1522 src
= mputprintf(src
,
1523 "int %s::JSON_decode(const TTCN_Typedescriptor_t&, JSON_Tokenizer& p_tok, boolean p_silent)\n"
1525 " json_token_t token = JSON_TOKEN_NONE;\n"
1526 " int dec_len = p_tok.get_next_token(&token, NULL, NULL);\n"
1527 " if (JSON_TOKEN_ERROR == token) {\n"
1528 " JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_BAD_TOKEN_ERROR, \"\");\n"
1529 " return JSON_ERROR_FATAL;\n"
1531 " else if (JSON_TOKEN_ARRAY_START != token) {\n"
1532 " return JSON_ERROR_INVALID_TOKEN;\n"
1536 " size_t buf_pos = p_tok.get_buf_pos();\n"
1537 " %s* val = new %s;\n"
1538 " int ret_val = val->JSON_decode(%s_descr_, p_tok, p_silent);\n"
1539 " if (JSON_ERROR_INVALID_TOKEN == ret_val) {\n"
1540 " p_tok.set_buf_pos(buf_pos);\n"
1544 " else if (JSON_ERROR_FATAL == ret_val) {\n"
1546 " if (p_silent) {\n"
1549 " return JSON_ERROR_FATAL;\n"
1551 " val_ptr->value_elements = (%s**)reallocate_pointers(\n"
1552 " (void**)val_ptr->value_elements, val_ptr->n_elements, val_ptr->n_elements + 1);\n"
1553 " val_ptr->value_elements[val_ptr->n_elements] = val;\n"
1554 " val_ptr->n_elements++;\n"
1555 " dec_len += ret_val;\n"
1557 " dec_len += p_tok.get_next_token(&token, NULL, NULL);\n"
1558 " if (JSON_TOKEN_ARRAY_END != token) {\n"
1559 " JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_REC_OF_END_TOKEN_ERROR, \"\");\n"
1560 " if (p_silent) {\n"
1563 " return JSON_ERROR_FATAL;\n"
1565 " return dec_len;\n"
1567 , name
, type
, type
, sdef
->oftypedescrname
, type
);
1570 def
= mputstr(def
, "};\n\n");
1572 output
->header
.class_decls
= mputprintf(output
->header
.class_decls
,
1573 "class %s;\n", name
);
1574 output
->header
.class_defs
= mputstr(output
->header
.class_defs
, def
);
1576 output
->source
.methods
= mputstr(output
->source
.methods
, src
);
1578 /* Copied from record.c. */
1579 output
->header
.function_prototypes
=
1580 mputprintf(output
->header
.function_prototypes
,
1581 "extern boolean operator==(null_type null_value, const %s& "
1582 "other_value);\n", name
);
1583 output
->source
.function_bodies
=
1584 mputprintf(output
->source
.function_bodies
,
1585 "boolean operator==(null_type, const %s& other_value)\n"
1587 "if (other_value.val_ptr == NULL)\n"
1588 "TTCN_error(\"The right operand of comparison is an unbound value of "
1590 "return other_value.val_ptr->n_elements == 0;\n"
1591 "}\n\n", name
, dispname
);
1593 output
->header
.function_prototypes
=
1594 mputprintf(output
->header
.function_prototypes
,
1595 "inline boolean operator!=(null_type null_value, const %s& "
1597 "{ return !(null_value == other_value); }\n", name
);
1600 /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
1602 void defRecordOfClassMemAllocOptimized(const struct_of_def
*sdef
, output_struct
*output
)
1604 char *def
= NULL
, *src
= NULL
;
1605 const char *name
= sdef
->name
, *dispname
= sdef
->dispname
;
1606 const char *type
= sdef
->type
;
1607 boolean ber_needed
= sdef
->isASN1
&& enable_ber();
1608 boolean raw_needed
= sdef
->hasRaw
&& enable_raw();
1609 boolean text_needed
= sdef
->hasText
&& enable_text();
1610 boolean xer_needed
= sdef
->hasXer
&& enable_xer();
1611 boolean json_needed
= sdef
->hasJson
&& enable_json();
1613 /* Class definition and private data members */
1614 def
= mputprintf(def
,
1616 "// written by %s in " __FILE__
" at %d\n"
1618 "class %s : public Base_Type {\n"
1620 "%s* value_elements;\n"
1622 , __FUNCTION__
, __LINE__
1626 /* private member functions */
1627 def
= mputprintf(def
,
1629 "friend boolean operator==(null_type null_value, "
1630 "const %s& other_value);\n", name
);
1632 def
= mputprintf(def
,
1633 "void copy_value(const %s& other_value);\n", name
);
1634 src
= mputprintf(src
,
1635 "void %s::copy_value(const %s& other_value)\n"
1637 "if (other_value.n_elements==-1) {\n"
1638 "TTCN_error(\"Copying an unbound value of type %s.\");\n"
1639 "} else if (other_value.n_elements==0) {\n"
1641 "value_elements = NULL;\n"
1643 "n_elements = other_value.n_elements;\n"
1644 "value_elements = new %s[n_elements];\n"
1645 "for (int act_elem=0; act_elem<n_elements; act_elem++) {\n"
1646 " if (other_value.value_elements[act_elem].is_bound()) {\n"
1647 " value_elements[act_elem] = other_value.value_elements[act_elem];\n"
1652 name
, name
, dispname
, type
);
1654 if (sdef
->kind
== SET_OF
) {
1655 /* callback function for comparison */
1656 def
= mputstr(def
, "static boolean compare_function("
1657 "const Base_Type *left_ptr, int left_index, "
1658 "const Base_Type *right_ptr, int right_index);\n");
1659 src
= mputprintf(src
, "boolean %s::compare_function("
1660 "const Base_Type *left_ptr, int left_index, "
1661 "const Base_Type *right_ptr, int right_index)\n"
1663 "if (((const %s*)left_ptr)->n_elements==-1) "
1664 "TTCN_error(\"The left operand of comparison is an unbound value of "
1666 "if (((const %s*)right_ptr)->n_elements==-1) "
1667 "TTCN_error(\"The right operand of comparison is an unbound value of "
1669 "if (((const %s*)left_ptr)->value_elements[left_index].is_bound()){\n"
1670 "if (((const %s*)right_ptr)->value_elements[right_index].is_bound()){\n"
1671 "return ((const %s*)left_ptr)->value_elements[left_index] == "
1672 "((const %s*)right_ptr)->value_elements[right_index];\n"
1673 "} else return FALSE;\n"
1675 "return !((const %s*)right_ptr)->value_elements[right_index].is_bound();\n"
1677 "}\n\n", name
, name
, dispname
, name
, dispname
, name
, name
, name
, name
, name
);
1680 /* public member functions */
1681 def
= mputstr(def
, "\npublic:\n");
1682 def
= mputprintf(def
, " typedef %s of_type;\n", sdef
->type
);
1685 def
= mputprintf(def
, "%s(): n_elements(-1), value_elements(NULL) {}\n", name
);
1687 def
= mputprintf(def
, "%s(null_type other_value): n_elements(0), value_elements(NULL) {}\n", name
);
1689 /* copy constructor */
1690 def
= mputprintf(def
, "%s(const %s& other_value) { copy_value(other_value); }\n", name
, name
);
1693 def
= mputprintf(def
, "~%s() { clean_up(); }\n\n", name
);
1695 /* clean_up function */
1696 def
= mputstr(def
, "void clean_up();\n");
1697 src
= mputprintf(src
,
1698 "void %s::clean_up()\n"
1700 "if (n_elements!=-1) {\n"
1701 "delete[] value_elements;\n"
1702 "n_elements = -1;\n"
1703 "value_elements = NULL;\n"
1707 /* assignment operators */
1708 def
= mputprintf(def
, "%s& operator=(null_type other_value);\n", name
);
1709 src
= mputprintf(src
,
1710 "%s& %s::operator=(null_type)\n"
1714 "value_elements=NULL;\n"
1716 "}\n\n", name
, name
);
1718 def
= mputprintf(def
, "%s& operator=(const %s& other_value);\n\n",
1720 src
= mputprintf(src
,
1721 "%s& %s::operator=(const %s& other_value)\n"
1723 "if (other_value.n_elements == -1) "
1724 "TTCN_error(\"Assigning an unbound value of type %s.\");\n"
1725 "if (this != &other_value) {\n"
1727 "copy_value(other_value);\n"
1730 "}\n\n", name
, name
, name
, dispname
);
1732 /* comparison operators */
1733 def
= mputstr(def
, "boolean operator==(null_type other_value) const;\n");
1734 src
= mputprintf(src
,
1735 "boolean %s::operator==(null_type) const\n"
1737 "if (n_elements==-1)\n"
1738 "TTCN_error(\"The left operand of comparison is an unbound value of "
1740 "return n_elements==0;\n"
1741 "}\n\n", name
, dispname
);
1743 def
= mputprintf(def
, "boolean operator==(const %s& other_value) const;\n",
1745 src
= mputprintf(src
,
1746 "boolean %s::operator==(const %s& other_value) const\n"
1748 "if (n_elements==-1) "
1749 "TTCN_error(\"The left operand of comparison is an unbound value of type "
1751 "if (other_value.n_elements==-1) "
1752 "TTCN_error(\"The right operand of comparison is an unbound value of type "
1754 "if (this==&other_value) return TRUE;\n", name
, name
,
1755 dispname
, dispname
);
1757 if (sdef
->kind
== SET_OF
) {
1759 "return compare_set_of(this, n_elements, &other_value, "
1760 "other_value.n_elements, compare_function);\n");
1763 "if (n_elements!=other_value.n_elements) return FALSE;\n"
1764 "for (int elem_count = 0; elem_count < n_elements; elem_count++){\n"
1765 "if (value_elements[elem_count].is_bound()){\n"
1766 "if (other_value.value_elements[elem_count].is_bound()){\n"
1767 " if (value_elements[elem_count] != "
1768 "other_value.value_elements[elem_count]) return FALSE;\n"
1769 "} else return FALSE;\n"
1771 "if (other_value.value_elements[elem_count].is_bound()) "
1777 src
= mputstr(src
, "}\n\n");
1779 def
= mputstr(def
, "inline boolean operator!=(null_type other_value) const "
1780 "{ return !(*this == other_value); }\n");
1781 def
= mputprintf(def
, "inline boolean operator!=(const %s& other_value) "
1782 "const { return !(*this == other_value); }\n\n", name
);
1784 /* indexing operators */
1785 /* Non-const operator[] is allowed to extend the record-of */
1786 def
= mputprintf(def
, "%s& operator[](int index_value);\n", type
);
1787 src
= mputprintf(src
,
1788 "%s& %s::operator[](int index_value)\n"
1790 "if (index_value < 0) TTCN_error(\"Accessing an element of type %s "
1791 "using a negative index: %%d.\", index_value);\n"
1792 "if (index_value >= n_elements) set_size(index_value + 1);\n"
1793 "return value_elements[index_value];\n"
1794 "}\n\n", type
, name
, dispname
);
1796 def
= mputprintf(def
, "%s& operator[](const INTEGER& index_value);\n",
1798 src
= mputprintf(src
,
1799 "%s& %s::operator[](const INTEGER& index_value)\n"
1801 "index_value.must_bound(\"Using an unbound integer value for indexing "
1802 "a value of type %s.\");\n"
1803 "return (*this)[(int)index_value];\n"
1804 "}\n\n", type
, name
, dispname
);
1806 /* Const operator[] throws an error if over-indexing */
1807 def
= mputprintf(def
, "const %s& operator[](int index_value) const;\n",
1809 src
= mputprintf(src
,
1810 "const %s& %s::operator[](int index_value) const\n"
1812 "if (n_elements==-1) TTCN_error(\"Accessing an element in an unbound "
1813 "value of type %s.\");\n"
1814 "if (index_value<0) TTCN_error(\"Accessing an element of type %s "
1815 "using a negative index: %%d.\", index_value);\n"
1816 "if (index_value>=n_elements) TTCN_error(\"Index overflow in a value "
1817 "of type %s: The index is %%d, but the value has only %%d elements.\""
1818 ", index_value, n_elements);\n"
1819 "return value_elements[index_value];\n"
1820 "}\n\n", type
, name
, dispname
, dispname
, dispname
);
1822 def
= mputprintf(def
, "const %s& operator[](const INTEGER& index_value) "
1823 "const;\n\n", type
);
1824 src
= mputprintf(src
,
1825 "const %s& %s::operator[](const INTEGER& index_value) const\n"
1827 "index_value.must_bound(\"Using an unbound integer value for indexing "
1828 "a value of type %s.\");\n"
1829 "return (*this)[(int)index_value];\n"
1830 "}\n\n", type
, name
, dispname
);
1832 /* rotation operators */
1833 def
= mputprintf(def
,
1834 "%s operator<<=(int rotate_count) const;\n"
1835 "%s operator<<=(const INTEGER& rotate_count) const;\n"
1836 "%s operator>>=(int rotate_count) const;\n"
1837 "%s operator>>=(const INTEGER& rotate_count) const;\n\n",
1838 name
, name
, name
, name
);
1839 src
= mputprintf(src
,
1840 "%s %s::operator<<=(int rotate_count) const\n"
1842 "return *this >>= (-rotate_count);\n"
1844 "%s %s::operator<<=(const INTEGER& rotate_count) const\n"
1846 "rotate_count.must_bound(\""
1847 "Unbound integer operand of rotate left operator.\");\n"
1848 "return *this >>= (int)(-rotate_count);\n"
1850 "%s %s::operator>>=(const INTEGER& rotate_count) const\n"
1852 "rotate_count.must_bound(\""
1853 "Unbound integer operand of rotate right operator.\");\n"
1854 "return *this >>= (int)rotate_count;\n"
1856 "%s %s::operator>>=(int rotate_count) const\n"
1858 "if (n_elements==-1) TTCN_error(\"Performing rotation operation on an "
1859 "unbound value of type %s.\");\n"
1860 "if (n_elements==0) return *this;\n"
1862 "if (rotate_count>=0) rc = rotate_count %% n_elements;\n"
1863 "else rc = n_elements - ((-rotate_count) %% n_elements);\n"
1864 "if (rc == 0) return *this;\n"
1866 "ret_val.set_size(n_elements);\n"
1867 "for (int i=0; i<n_elements; i++) {\n"
1868 "if (value_elements[i].is_bound()) "
1869 "ret_val.value_elements[(i+rc)%%n_elements] = value_elements[i];\n"
1873 name
, name
, name
, name
, name
, name
, name
, name
, dispname
, name
);
1876 def
= mputprintf(def
,
1877 "%s operator+(const %s& other_value) const;\n\n", name
, name
);
1878 src
= mputprintf(src
,
1879 "%s %s::operator+(const %s& other_value) const\n"
1881 "if (n_elements==-1 || other_value.n_elements==-1) "
1882 "TTCN_error(\"Unbound operand of %s concatenation.\");\n"
1883 "if (n_elements==0) return other_value;\n"
1884 "if (other_value.n_elements==0) return *this;\n"
1886 "ret_val.set_size(n_elements+other_value.n_elements);\n"
1887 "for (int i=0; i<n_elements; i++) {\n"
1888 "if (value_elements[i].is_bound()) "
1889 "ret_val.value_elements[i] = value_elements[i];\n"
1891 "for (int i=0; i<other_value.n_elements; i++) {\n"
1892 "if (other_value.value_elements[i].is_bound()) "
1893 "ret_val.value_elements[i+n_elements] = other_value.value_elements[i];\n"
1896 "}\n\n", name
, name
, name
, dispname
, name
);
1899 def
= mputprintf(def
,
1900 "%s substr(int index, int returncount) const;\n\n", name
);
1901 src
= mputprintf(src
,
1902 "%s %s::substr(int index, int returncount) const\n"
1904 "if (n_elements==-1) TTCN_error(\"The first argument of substr() is an "
1905 "unbound value of type %s.\");\n"
1906 "check_substr_arguments(n_elements, index, returncount, \"%s\",\"element\");\n"
1908 "ret_val.set_size(returncount);\n"
1909 "for (int i=0; i<returncount; i++) {\n"
1910 "if (value_elements[i+index].is_bound()) "
1911 "ret_val.value_elements[i] = value_elements[i+index];\n"
1914 "}\n\n", name
, name
, dispname
, dispname
, name
);
1917 def
= mputprintf(def
,
1918 "%s replace(int index, int len, const %s& repl) const;\n\n", name
, name
);
1919 src
= mputprintf(src
,
1920 "%s %s::replace(int index, int len, const %s& repl) const\n"
1922 "if (n_elements==-1) TTCN_error(\"The first argument of replace() is an "
1923 "unbound value of type %s.\");\n"
1924 "if (repl.n_elements==-1) TTCN_error(\"The fourth argument of replace() "
1925 "is an unbound value of type %s.\");\n"
1926 "check_replace_arguments(n_elements, index, len, \"%s\",\"element\");\n"
1928 "ret_val.set_size(n_elements + repl.n_elements - len);\n"
1929 "for (int i = 0; i < index; i++) {\n"
1930 "if (value_elements[i].is_bound()) "
1931 "ret_val.value_elements[i] = value_elements[i];\n"
1933 "for (int i = 0; i < repl.n_elements; i++) {\n"
1934 "if (repl.value_elements[i].is_bound()) "
1935 "ret_val.value_elements[i+index] = repl.value_elements[i];\n"
1937 "for (int i = 0; i < n_elements - index - len; i++) {\n"
1938 "if (value_elements[index+i+len].is_bound()) "
1939 "ret_val.value_elements[index+i+repl.n_elements] = value_elements[index+i+len];\n"
1942 "}\n\n", name
, name
, name
, dispname
, dispname
, dispname
, name
);
1943 def
= mputprintf(def
,
1944 "%s replace(int index, int len, const %s_template& repl) const;\n\n",
1946 src
= mputprintf(src
,
1947 "%s %s::replace(int index, int len, const %s_template& repl) const\n"
1949 "if (!repl.is_value()) TTCN_error(\"The fourth argument of function "
1950 "replace() is a template with non-specific value.\");\n"
1951 "return replace(index, len, repl.valueof());\n"
1952 "}\n\n", name
, name
, name
);
1954 /* set_size function */
1955 def
= mputstr(def
, "void set_size(int new_size);\n");
1956 src
= mputprintf(src
, "void %s::set_size(int new_size)\n"
1958 "if (new_size<0) TTCN_error(\"Internal error: Setting a negative size for "
1959 "a value of type %s.\");\n"
1960 "if (new_size==n_elements) return;\n"
1961 "if (new_size==0) {\n"
1963 " n_elements = 0;\n"
1964 " value_elements = NULL;\n"
1967 "%s* new_elem_v = new %s[new_size];\n"
1968 "for (int act_elem = 0; act_elem<n_elements; act_elem++) {\n"
1969 " if (act_elem>=new_size) break;\n"
1970 " if (value_elements[act_elem].is_bound()) new_elem_v[act_elem] = value_elements[act_elem];\n"
1973 "#ifdef TITAN_MEMORY_DEBUG_SET_RECORD_OF\n"
1974 "if((n_elements/1000)!=(new_size/1000)) "
1975 "TTCN_warning(\"New size of type %s: %%d\",new_size);\n"
1977 "n_elements = new_size;\n"
1978 "value_elements = new_elem_v;\n"
1979 "}\n\n", name
, dispname
, type
, type
, dispname
);
1981 /* is_bound function */
1983 "inline boolean is_bound() const {return n_elements!=-1; }\n");
1985 /* is_present function */
1987 "inline boolean is_present() const { return is_bound(); }\n");
1989 /* is_value function */
1991 "boolean is_value() const;\n");
1992 src
= mputprintf(src
,
1993 "boolean %s::is_value() const\n"
1995 "if (n_elements==-1) return FALSE;\n"
1996 "for (int i = 0; i < n_elements; ++i) {\n"
1997 " if (!value_elements[i].is_value()) return FALSE;\n"
2002 /* sizeof operation */
2004 "int size_of() const;\n"
2005 "int n_elem() const { return size_of(); }\n");
2006 src
= mputprintf(src
,
2007 "int %s::size_of() const\n"
2009 "if (n_elements==-1) TTCN_error(\"Performing sizeof operation on an "
2010 "unbound value of type %s.\");\n"
2011 "return n_elements;\n"
2012 "}\n\n", name
, dispname
);
2014 /* lengthof operation */
2015 def
= mputstr(def
, "int lengthof() const;\n");
2016 src
= mputprintf(src
,
2017 "int %s::lengthof() const\n"
2019 "if (n_elements==-1) TTCN_error(\"Performing lengthof operation on an "
2020 "unbound value of type %s.\");\n"
2021 "for (int my_length=n_elements; my_length>0; my_length--) "
2022 "if (value_elements[my_length-1].is_bound()) return my_length;\n"
2024 "}\n\n", name
, dispname
);
2027 def
= mputstr(def
, "void log() const;\n");
2028 src
= mputprintf(src
,
2029 "void %s::log() const\n"
2031 "if (n_elements==-1) {;\n"
2032 "TTCN_Logger::log_event_unbound();\n"
2035 "switch (n_elements) {\n"
2037 "TTCN_Logger::log_event_str(\"{ }\");\n"
2040 "TTCN_Logger::log_event_str(\"{ \");\n"
2041 "for (int elem_count = 0; elem_count < n_elements; elem_count++) {\n"
2042 "if (elem_count > 0) TTCN_Logger::log_event_str(\", \");\n"
2043 "value_elements[elem_count].log();\n"
2045 "TTCN_Logger::log_event_str(\" }\");\n"
2049 /* set_param function */ /* this is an exact copy of the previous one in this source file, if we didn't forget... */
2050 def
= mputstr(def
, "void set_param(Module_Param& param);\n");
2051 src
= mputprintf(src
,
2052 "void %s::set_param(Module_Param& param)\n"
2054 " if (dynamic_cast<Module_Param_Name*>(param.get_id()) != NULL &&\n"
2055 " param.get_id()->next_name()) {\n"
2056 // Haven't reached the end of the module parameter name
2057 // => the name refers to one of the elements, not to the whole record of
2058 " char* param_field = param.get_id()->get_current_name();\n"
2059 " if (param_field[0] < '0' || param_field[0] > '9') {\n"
2060 " param.error(\"Unexpected record field name in module parameter, expected a valid\"\n"
2061 " \" index for %s type `%s'\");\n"
2063 " int param_index = -1;\n"
2064 " sscanf(param_field, \"%%d\", ¶m_index);\n"
2065 " (*this)[param_index].set_param(param);\n"
2068 " param.basic_check(Module_Param::BC_VALUE|Module_Param::BC_LIST, \"%s value\");\n"
2069 " switch (param.get_operation_type()) {\n"
2070 " case Module_Param::OT_ASSIGN:\n"
2071 " if (param.get_type()==Module_Param::MP_Value_List && param.get_size()==0) {\n"
2072 " *this = NULL_VALUE;\n"
2075 " switch (param.get_type()) {\n"
2076 " case Module_Param::MP_Value_List:\n"
2077 " set_size(param.get_size());\n"
2078 " for (size_t i=0; i<param.get_size(); ++i) {\n"
2079 " Module_Param* const curr = param.get_elem(i);\n"
2080 " if (curr->get_type()!=Module_Param::MP_NotUsed) {\n"
2081 " (*this)[i].set_param(*curr);\n"
2085 " case Module_Param::MP_Indexed_List:\n"
2086 " for (size_t i=0; i<param.get_size(); ++i) {\n"
2087 " Module_Param* const curr = param.get_elem(i);\n"
2088 " (*this)[curr->get_id()->get_index()].set_param(*curr);\n"
2092 " param.type_error(\"%s value\", \"%s\");\n"
2095 " case Module_Param::OT_CONCAT:\n"
2096 " switch (param.get_type()) {\n"
2097 " case Module_Param::MP_Value_List: {\n"
2098 " if (!is_bound()) *this = NULL_VALUE;\n"
2099 " int start_idx = lengthof();\n"
2100 " for (size_t i=0; i<param.get_size(); ++i) {\n"
2101 " Module_Param* const curr = param.get_elem(i);\n"
2102 " if ((curr->get_type()!=Module_Param::MP_NotUsed)) {\n"
2103 " (*this)[start_idx+(int)i].set_param(*curr);\n"
2107 " case Module_Param::MP_Indexed_List:\n"
2108 " param.error(\"Cannot concatenate an indexed value list\");\n"
2111 " param.type_error(\"%s value\", \"%s\");\n"
2115 " TTCN_error(\"Internal error: Unknown operation type.\");\n"
2117 "}\n", name
, sdef
->kind
== RECORD_OF
? "record of" : "set of", dispname
,
2118 sdef
->kind
== RECORD_OF
? "record of" : "set of",
2119 sdef
->kind
== RECORD_OF
? "record of" : "set of", dispname
,
2120 sdef
->kind
== RECORD_OF
? "record of" : "set of", dispname
);
2122 /* encoding / decoding functions */
2123 def
= mputstr(def
, "void encode_text(Text_Buf& text_buf) const;\n");
2124 src
= mputprintf(src
,
2125 "void %s::encode_text(Text_Buf& text_buf) const\n"
2127 "if (n_elements==-1) "
2128 "TTCN_error(\"Text encoder: Encoding an unbound value of type %s.\");\n"
2129 "text_buf.push_int(n_elements);\n"
2130 "for (int elem_count = 0; elem_count < n_elements; elem_count++)\n"
2131 "value_elements[elem_count].encode_text(text_buf);\n"
2132 "}\n\n", name
, dispname
);
2134 def
= mputstr(def
, "void decode_text(Text_Buf& text_buf);\n");
2135 src
= mputprintf(src
,
2136 "void %s::decode_text(Text_Buf& text_buf)\n"
2139 "n_elements = text_buf.pull_int().get_val();\n"
2140 "if (n_elements < 0) TTCN_error(\"Text decoder: Negative size "
2141 "was received for a value of type %s.\");\n"
2142 "if (n_elements==0) {\n"
2143 " value_elements = NULL;\n"
2146 "value_elements = new %s[n_elements];\n"
2147 "for (int elem_count = 0; elem_count < n_elements; elem_count++) {\n"
2148 " value_elements[elem_count].decode_text(text_buf);\n"
2150 "}\n\n", name
, dispname
, type
);
2152 if(ber_needed
|| raw_needed
|| text_needed
|| xer_needed
|| json_needed
)
2153 def_encdec(name
, &def
, &src
, ber_needed
, raw_needed
, text_needed
,
2154 xer_needed
, json_needed
, FALSE
);
2158 "int %s::TEXT_encode(const TTCN_Typedescriptor_t& p_td,"
2159 " TTCN_Buffer& p_buf) const{\n"
2160 " int encoded_length=0;\n"
2161 " if(p_td.text->begin_encode){\n"
2162 " p_buf.put_cs(*p_td.text->begin_encode);\n"
2163 " encoded_length+=p_td.text->begin_encode->lengthof();\n"
2165 " if(n_elements==-1) {\n"
2166 " TTCN_EncDec_ErrorContext::error\n"
2167 " (TTCN_EncDec::ET_UNBOUND, \"Encoding an unbound value.\");\n"
2168 " if(p_td.text->end_encode){\n"
2169 " p_buf.put_cs(*p_td.text->end_encode);\n"
2170 " encoded_length+=p_td.text->end_encode->lengthof();\n"
2172 " return encoded_length;\n"
2174 " for(int a=0;a<n_elements;a++){\n"
2175 " if(a!=0 && p_td.text->separator_encode){\n"
2176 " p_buf.put_cs(*p_td.text->separator_encode);\n"
2177 " encoded_length+=p_td.text->separator_encode->lengthof();\n"
2179 " encoded_length+=value_elements[a].TEXT_encode(%s_descr_,p_buf);\n"
2181 " if(p_td.text->end_encode){\n"
2182 " p_buf.put_cs(*p_td.text->end_encode);\n"
2183 " encoded_length+=p_td.text->end_encode->lengthof();\n"
2185 " return encoded_length;\n"
2187 ,name
,sdef
->oftypedescrname
2189 src
= mputprintf(src
,
2190 "int %s::TEXT_decode(const TTCN_Typedescriptor_t& p_td,"
2191 " TTCN_Buffer& p_buf, Limit_Token_List& limit, boolean no_err"
2192 ", boolean first_call){\n"
2193 " int decoded_length=0;\n"
2194 " size_t pos=p_buf.get_pos();\n"
2195 " boolean sep_found=FALSE;\n"
2196 " int sep_length=0;\n"
2198 " if(p_td.text->begin_decode){\n"
2200 " if((tl=p_td.text->begin_decode->match_begin(p_buf))<0){\n"
2201 " if(no_err)return -1;\n"
2202 " TTCN_EncDec_ErrorContext::error\n"
2203 " (TTCN_EncDec::ET_TOKEN_ERR, \"The specified token '%%s'"
2204 " not found for '%%s': \",(const char*)*(p_td.text->begin_decode)"
2208 " decoded_length+=tl;\n"
2209 " p_buf.increase_pos(tl);\n"
2211 " if(p_td.text->end_decode){\n"
2212 " limit.add_token(p_td.text->end_decode);\n"
2215 " if(p_td.text->separator_decode){\n"
2216 " limit.add_token(p_td.text->separator_decode);\n"
2219 " if(first_call) {\n"
2222 " int more=n_elements;\n"
2225 " pos=p_buf.get_pos();\n"
2226 " int len=val.TEXT_decode(%s_descr_,p_buf,limit,TRUE);\n"
2227 " if(len==-1 || (len==0 && !limit.has_token())){\n"
2228 " p_buf.set_pos(pos);\n"
2230 " p_buf.set_pos(p_buf.get_pos()-sep_length);\n"
2231 " decoded_length-=sep_length;\n"
2235 " sep_found=FALSE;\n"
2236 " set_size(n_elements+1);\n"
2237 " value_elements[n_elements-1]=val;\n"
2238 " decoded_length+=len;\n"
2239 " if(p_td.text->separator_decode){\n"
2241 " if((tl=p_td.text->separator_decode->match_begin(p_buf))<0){\n"
2244 " decoded_length+=tl;\n"
2245 " p_buf.increase_pos(tl);\n"
2247 " sep_found=TRUE;\n"
2248 " } else if(p_td.text->end_decode){\n"
2250 " if((tl=p_td.text->end_decode->match_begin(p_buf))!=-1){\n"
2251 " decoded_length+=tl;\n"
2252 " p_buf.increase_pos(tl);\n"
2253 " limit.remove_tokens(ml);\n"
2254 " return decoded_length;\n"
2256 " } else if(limit.has_token(ml)){\n"
2258 " if((tl=limit.match(p_buf,ml))==0){\n"
2259 " sep_found=FALSE;\n"
2264 ,name
,type
,sdef
->oftypedescrname
2267 " limit.remove_tokens(ml);\n"
2268 " if(p_td.text->end_decode){\n"
2270 " if((tl=p_td.text->end_decode->match_begin(p_buf))<0){\n"
2272 " if(!first_call){\n"
2273 " set_size(more);\n"
2277 " TTCN_EncDec_ErrorContext::error"
2278 "(TTCN_EncDec::ET_TOKEN_ERR, \"The specified token '%s'"
2279 " not found for '%s': \",(const char*)*(p_td.text->end_decode)"
2281 " return decoded_length;\n"
2283 " decoded_length+=tl;\n"
2284 " p_buf.increase_pos(tl);\n"
2286 " if(n_elements==0){\n"
2287 " if(p_td.text->end_decode || p_td.text->begin_decode) n_elements=0;\n"
2289 " if(no_err)return -1;\n"
2290 " TTCN_EncDec_ErrorContext::error"
2291 "(TTCN_EncDec::ET_TOKEN_ERR, \"No record/set of member found.\");\n"
2292 " return decoded_length;\n"
2295 " if(!first_call && more==n_elements && "
2296 "!(p_td.text->end_decode || p_td.text->begin_decode)) return -1;\n"
2297 " return decoded_length;\n"
2304 /* BER_encode_TLV() */
2307 "ASN_BER_TLV_t* %s::BER_encode_TLV(const TTCN_Typedescriptor_t&"
2308 " p_td, unsigned p_coding) const\n"
2310 " BER_chk_descr(p_td);\n"
2311 " ASN_BER_TLV_t *new_tlv=BER_encode_chk_bound(is_bound());\n"
2313 " new_tlv=ASN_BER_TLV_t::construct(NULL);\n"
2314 " TTCN_EncDec_ErrorContext ec;\n"
2315 " for(int elem_i=0; elem_i<n_elements; elem_i++) {\n"
2316 " ec.set_msg(\"Component #%%d: \", elem_i);\n"
2317 " new_tlv->add_TLV(value_elements[elem_i].BER_encode_TLV"
2318 "(%s_descr_, p_coding));\n"
2322 " new_tlv=ASN_BER_V2TLV(new_tlv, p_td, p_coding);\n"
2323 " return new_tlv;\n"
2326 /* BER_decode_TLV() */
2327 "boolean %s::BER_decode_TLV(const TTCN_Typedescriptor_t& p_td,"
2328 " const ASN_BER_TLV_t& p_tlv, unsigned L_form)\n"
2330 " BER_chk_descr(p_td);\n"
2331 " ASN_BER_TLV_t stripped_tlv;\n"
2332 " BER_decode_strip_tags(*p_td.ber, p_tlv, L_form, stripped_tlv);\n"
2333 " TTCN_EncDec_ErrorContext ec_0(\"While decoding '%%s' type: \","
2335 " stripped_tlv.chk_constructed_flag(TRUE);\n"
2337 " size_t V_pos=0;\n"
2338 " ASN_BER_TLV_t tmp_tlv;\n"
2339 " TTCN_EncDec_ErrorContext ec_1(\"Component #\");\n"
2340 " TTCN_EncDec_ErrorContext ec_2(\"0: \");\n"
2341 " while(BER_decode_constdTLV_next(stripped_tlv, V_pos, L_form, "
2343 " set_size(n_elements+1);\n"
2344 " value_elements[n_elements-1].BER_decode_TLV(%s_descr_, tmp_tlv, "
2346 " ec_2.set_msg(\"%%d: \", n_elements);\n"
2351 , name
, sdef
->oftypedescrname
2352 , sdef
->kind
==SET_OF
?" new_tlv->sort_tlvs();\n":""
2353 , name
, sdef
->oftypedescrname
2356 if(sdef
->has_opentypes
) {
2357 /* BER_decode_opentypes() */
2360 "void BER_decode_opentypes(TTCN_Type_list& p_typelist,"
2361 " unsigned L_form);\n");
2364 "void %s::BER_decode_opentypes(TTCN_Type_list& p_typelist,"
2365 " unsigned L_form)\n"
2367 " p_typelist.push(this);\n"
2368 " TTCN_EncDec_ErrorContext ec_0(\"Component #\");\n"
2369 " TTCN_EncDec_ErrorContext ec_1;\n"
2370 " for(int elem_i=0; elem_i<n_elements; elem_i++) {\n"
2371 " ec_1.set_msg(\"%%d: \", elem_i);\n"
2372 " value_elements[elem_i].BER_decode_opentypes(p_typelist,"
2375 " p_typelist.pop();\n"
2385 "int %s::RAW_decode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf, "
2386 "int limit, raw_order_t top_bit_ord, boolean /*no_err*/, int sel_field"
2387 ", boolean first_call){\n"
2388 " int prepaddlength=p_buf.increase_pos_padd(p_td.raw->prepadding);\n"
2389 " limit-=prepaddlength;\n"
2390 " int decoded_length=0;\n"
2391 " int decoded_field_length=0;\n"
2392 " size_t start_of_field=0;\n"
2393 " if (first_call) set_size(0);\n"
2394 " int start_field=n_elements;\n"
2395 " if(p_td.raw->fieldlength || sel_field!=-1){\n"
2397 " if(sel_field==-1) sel_field=p_td.raw->fieldlength;\n"
2398 " for(a=0;a<sel_field;a++){\n"
2399 " decoded_field_length=(*this)[a+start_field].RAW_decode(%s_descr_,"
2400 "p_buf,limit,top_bit_ord,TRUE);\n"
2401 " if(decoded_field_length < 0) return decoded_field_length;\n"
2402 " decoded_length+=decoded_field_length;\n"
2403 " limit-=decoded_field_length;\n"
2405 " if(a==0) n_elements=0;\n"
2407 " int a=start_field;\n"
2409 " if(!first_call) return -1;\n"
2411 " return decoded_length+p_buf.increase_pos_padd(p_td.raw->padding)"
2414 " while(limit>0){\n"
2415 " start_of_field=p_buf.get_pos_bit();\n"
2416 " decoded_field_length=(*this)[a].RAW_decode(%s_descr_,p_buf,limit,"
2417 "top_bit_ord,TRUE);\n"
2418 " if(decoded_field_length < 0){\n"
2419 /*" delete &(*this)[a];\n"*/
2421 " p_buf.set_pos_bit(start_of_field);\n"
2422 " if(a>start_field){\n"
2423 " return decoded_length+p_buf.increase_pos_padd(p_td.raw->padding)"
2425 " } else return -1;\n"
2427 " decoded_length+=decoded_field_length;\n"
2428 " limit-=decoded_field_length;\n"
2430 ,name
,sdef
->oftypedescrname
,sdef
->oftypedescrname
2432 if(sdef
->raw
.extension_bit
!=XDEFNO
&& sdef
->raw
.extension_bit
!=XDEFDEFAULT
){
2434 " if (%sp_buf.get_last_bit())\n"
2435 " return decoded_length+p_buf.increase_pos_padd(p_td.raw->padding)"
2436 "+prepaddlength;\n", sdef
->raw
.extension_bit
== XDEFYES
? "" : "!");
2441 " return decoded_length+p_buf.increase_pos_padd(p_td.raw->padding)"
2444 "int %s::RAW_encode(const TTCN_Typedescriptor_t& p_td,"
2445 "RAW_enc_tree& myleaf) const{\n"
2446 " int encoded_length=0;\n"
2447 " int encoded_num_of_records=p_td.raw->fieldlength?"
2448 "smaller(n_elements, p_td.raw->fieldlength):n_elements;\n"
2449 " myleaf.isleaf=FALSE;\n"
2450 " myleaf.rec_of=TRUE;\n"
2451 " myleaf.body.node.num_of_nodes=encoded_num_of_records;\n"
2452 " myleaf.body.node.nodes=init_nodes_of_enc_tree(encoded_num_of_records);\n"
2453 " for(int a=0;a<encoded_num_of_records;a++){\n"
2454 " myleaf.body.node.nodes[a]=new RAW_enc_tree(TRUE,&myleaf,"
2455 "&(myleaf.curr_pos),a,%s_descr_.raw);\n"
2456 " encoded_length+=(*this)[a].RAW_encode(%s_descr_,"
2457 "*myleaf.body.node.nodes[a]);\n"
2459 " return myleaf.length=encoded_length;\n}\n\n"
2460 , name
, sdef
->oftypedescrname
, sdef
->oftypedescrname
2464 if (xer_needed
) { /* XERSTUFF encoder codegen for record-of, RT1 */
2466 "char **collect_ns(const XERdescriptor_t& p_td, size_t& num, bool& def_ns) const;\n");
2468 /* Write the body of the XER encoder/decoder functions. The declaration
2469 * is written by def_encdec() in encdec.c */
2470 src
= mputprintf(src
,
2471 "boolean %s::can_start(const char *name, const char *uri, "
2472 "XERdescriptor_t const& xd, unsigned int flavor) {\n"
2473 " boolean e_xer = is_exer(flavor);\n"
2474 " if (e_xer && (xd.xer_bits & ANY_ELEMENT)) "
2477 if (sdef
->nFollowers
) {
2478 /* If there are optional fields following the record-of, then seeing
2479 * {any XML tag that belongs to those fields} where the record-of may be
2480 * means that the record-of is empty. */
2482 src
= mputstr(src
, "{\n");
2483 for (f
= 0; f
< sdef
->nFollowers
; ++f
) {
2484 src
= mputprintf(src
,
2485 " if (%s::can_start(name, uri, %s_xer_, flavor)) return FALSE;\n"
2486 , sdef
->followers
[f
].type
2487 , sdef
->followers
[f
].typegen
2494 else src
= mputstr(src
, "return TRUE;\n");
2496 src
= mputprintf(src
,
2497 " if ((!e_xer || !(xd.xer_bits & UNTAGGED)) && !(flavor & XER_RECOF)) return "
2498 "check_name(name, xd, e_xer) && (!e_xer || check_namespace(uri, xd));\n"
2499 " else return %s::can_start(name, uri, %s_xer_, flavor | XER_RECOF);\n"
2502 , sdef
->oftypedescrname
2505 src
= mputprintf(src
,
2506 "char ** %s::collect_ns(const XERdescriptor_t& p_td, size_t& num, bool& def_ns) const {\n"
2507 " size_t num_collected;\n"
2508 " char **collected_ns = Base_Type::collect_ns(p_td, num_collected, def_ns);\n"
2509 /* The above may throw but then nothing was allocated. */
2510 " if (n_elements!=-1) try {\n"
2512 " size_t num_new;\n"
2513 " for (int i = 0; i < n_elements; ++i) {\n"
2514 " bool def_ns_1 = false;"
2515 " new_ns = value_elements[i].collect_ns(%s_xer_, num_new, def_ns_1);\n"
2516 " merge_ns(collected_ns, num_collected, new_ns, num_new);\n"
2517 " def_ns = def_ns || def_ns_1;\n" /* alas, no ||= */
2521 /* Probably a TC_Error thrown from elements[i]->collect_ns() if e.g.
2522 * encoding an unbound value. */
2523 " while (num_collected > 0) Free(collected_ns[--num_collected]);\n"
2524 " Free(collected_ns);\n"
2527 " num = num_collected;\n"
2528 " return collected_ns;\n"
2530 , name
, sdef
->oftypedescrname
);
2533 "int %s::XER_encode(const XERdescriptor_t& p_td, TTCN_Buffer& p_buf, "
2534 "unsigned int p_flavor, int p_indent, embed_values_enc_struct_t* emb_val) const\n{\n"
2535 " if (n_elements==-1) TTCN_error(\"Attempt to XER-encode an unbound record of\");\n" /* TODO type name */
2536 " int encoded_length=(int)p_buf.get_len();\n"
2537 " boolean e_xer = is_exer(p_flavor);\n"
2538 " boolean own_tag = !(e_xer && p_indent && ((p_td.xer_bits & (ANY_ELEMENT|ANY_ATTRIBUTES|UNTAGGED))\n"
2539 " || (p_flavor & USE_TYPE_ATTR)));\n"
2540 " boolean indenting = !is_canonical(p_flavor) && own_tag;\n"
2541 "%s" /* Factor out p_indent if not attribute */
2542 " if (n_elements==0) {\n" /* Empty record of */
2544 , sdef
->xerAttribute
? "" : " if (indenting) do_indent(p_buf, p_indent);\n"
2546 if (sdef
->xerAttribute
) {
2548 " if (e_xer) {\n" /* Empty attribute. */
2549 " begin_attribute(p_td, p_buf);\n"
2550 " p_buf.put_c('\\'');\n"
2558 " {\n" /* Do empty element tag */
2560 " p_buf.put_c('<');\n"
2561 " if (e_xer) write_ns_prefix(p_td, p_buf);\n"
2562 " p_buf.put_s((size_t)p_td.namelens[e_xer]-2, (const unsigned char*)p_td.names[e_xer]);\n"
2563 /* namespace declarations for the toplevel element */
2564 " if (e_xer && p_indent==0)\n"
2566 " size_t num_collected = 0;\n"
2567 " char **collected_ns = NULL;\n"
2568 " bool def_ns = false;\n"
2569 " collected_ns = collect_ns(p_td, num_collected, def_ns);\n"
2570 " for (size_t cur_coll = 0; cur_coll < num_collected; ++cur_coll) {\n"
2571 " p_buf.put_s(strlen(collected_ns[cur_coll]), (cbyte*)collected_ns[cur_coll]);\n"
2572 " Free(collected_ns[cur_coll]);\n"
2574 " Free(collected_ns);\n"
2577 " p_buf.put_s(2 + indenting, (const unsigned char*)\"/>\\n\");\n"
2580 " else {\n" /* Not empty record of. Start tag or attribute */
2581 , sdef
->xerAttribute
? " if (indenting) do_indent(p_buf, p_indent);\n" : ""
2583 if (sdef
->xerAnyAttrElem
) {
2585 " if (e_xer && (p_td.xer_bits & ANY_ATTRIBUTES)) {\n"
2586 " static const universal_char sp = { 0,0,0,' ' };\n"
2587 " static const universal_char tb = { 0,0,0,9 };\n"
2588 " size_t buf_len = p_buf.get_len(), shorter = 0;\n"
2589 " const unsigned char * const buf_data = p_buf.get_data();\n"
2590 " if (buf_data[buf_len - 1 - shorter] == '\\n') ++shorter;\n"
2591 " if (buf_data[buf_len - 1 - shorter] == '>' ) ++shorter;\n"
2592 " unsigned char saved[4];\n"
2593 " memcpy(saved, buf_data + (buf_len - shorter), shorter);\n"
2594 " p_buf.increase_length(-shorter);\n"
2595 " for (int i = 0; i < n_elements; ++i) {\n"
2596 " TTCN_EncDec_ErrorContext ec_0(\"Attribute %d: \", i);\n"
2597 " size_t len = value_elements[i].lengthof();\n"
2599 " const UNIVERSAL_CHARSTRING_ELEMENT& ue = value_elements[i][len - 1];\n"
2600 " if (sp == ue || tb == ue) --len;\n"
2603 " size_t j, sp_at = 0;\n"
2604 /* Find the "separators" in each string */
2605 " for (j = 0; j < len; j++) {\n"
2606 " UNIVERSAL_CHARSTRING_ELEMENT ue = value_elements[i][j];\n"
2608 " if (sp == ue || tb == ue) {}\n"
2611 " if (sp == ue || tb == ue) sp_at = j;\n"
2614 " size_t buf_start = p_buf.get_len();\n"
2615 /* Now write them */
2616 " if (sp_at > 0) {\n"
2617 " char * ns = mprintf(\" xmlns:b%d='\", i);\n"
2618 " size_t ns_len = mstrlen(ns);\n"
2619 " p_buf.put_s(ns_len, (const unsigned char*)ns);\n"
2621 " UNIVERSAL_CHARSTRING before(sp_at, (const universal_char*)(value_elements[i]));\n"
2622 " before.XER_encode(UNIVERSAL_CHARSTRING_xer_, p_buf, p_flavor | ANY_ATTRIBUTES, p_indent, 0);\n"
2623 // Ensure the namespace abides to its restrictions
2624 " if (p_td.xer_bits & (ANY_FROM | ANY_EXCEPT)) {\n"
2625 " TTCN_Buffer ns_buf;\n"
2626 " before.encode_utf8(ns_buf);\n"
2628 " ns_buf.get_string(cs);\n"
2629 " check_namespace_restrictions(p_td, (const char*)cs);\n"
2632 " p_buf.put_c('\\'');\n"
2633 " p_buf.put_c(' ');\n"
2635 /* Keep just the "b%d" part from ns */
2636 " p_buf.put_s(ns_len - 9, (const unsigned char*)ns + 7);\n"
2637 " p_buf.put_c(':');\n"
2641 " p_buf.put_c(' ');\n"
2643 // Make sure the unqualified namespace is allowed
2644 " if (p_td.xer_bits & (ANY_FROM | ANY_EXCEPT)) {\n"
2645 " check_namespace_restrictions(p_td, NULL);\n"
2649 " UNIVERSAL_CHARSTRING after(len - j, (const universal_char*)(value_elements[i]) + j);\n"
2650 " after.XER_encode(UNIVERSAL_CHARSTRING_xer_, p_buf, p_flavor | ANY_ATTRIBUTES, p_indent, 0);\n"
2651 // Put this attribute in a dummy element and walk through it to check its validity
2652 " TTCN_Buffer check_buf;\n"
2653 " check_buf.put_s(2, (unsigned char*)\"<a\");\n"
2654 " check_buf.put_s(p_buf.get_len() - buf_start, p_buf.get_data() + buf_start);\n"
2655 " check_buf.put_s(2, (unsigned char*)\"/>\");"
2656 " XmlReaderWrap checker(check_buf);\n"
2657 " while (1 == checker.Read()) ;\n"
2660 " p_buf.put_s(shorter, saved);\n" /* restore the '>' and anything after */
2663 if (sdef
->xerAttribute
) {
2666 " begin_attribute(p_td, p_buf);\n"
2672 " p_buf.put_c('<');\n"
2673 " boolean write_ns = (e_xer && p_indent==0);\n"
2674 " boolean keep_newline = (indenting && !(e_xer && (p_td.xer_bits & XER_LIST)));\n"
2675 " if (e_xer) write_ns_prefix(p_td, p_buf);\n"
2676 " p_buf.put_s((size_t)p_td.namelens[e_xer]-write_ns-(write_ns || !keep_newline), "
2677 "(const unsigned char*)p_td.names[e_xer]);\n"
2679 /* namespace declarations for the toplevel element */
2680 " if (e_xer && p_indent==0)\n"
2682 " size_t num_collected = 0;\n"
2683 " char **collected_ns = NULL;\n"
2684 " bool def_ns = false;\n"
2685 " collected_ns = collect_ns(p_td, num_collected, def_ns);\n"
2686 " for (size_t cur_coll = 0; cur_coll < num_collected; ++cur_coll) {\n"
2687 " p_buf.put_s(strlen(collected_ns[cur_coll]), (cbyte*)collected_ns[cur_coll]);\n"
2688 " Free(collected_ns[cur_coll]);\n"
2690 " Free(collected_ns);\n"
2691 " p_buf.put_s(1 + keep_newline, (cbyte*)\">\\n\");\n"
2693 , sdef
->xerAttribute
? " if (indenting) do_indent(p_buf, p_indent);\n" : ""
2695 if (sdef
->xmlValueList
) {
2696 src
=mputstr(src
, " if (indenting && !e_xer) do_indent(p_buf, p_indent+1);\n"); /* !e_xer or GDMO */
2700 " p_flavor |= XER_RECOF | (p_td.xer_bits & XER_LIST);\n"
2701 " TTCN_EncDec_ErrorContext ec_0(\"Index \");\n"
2702 " TTCN_EncDec_ErrorContext ec_1;\n"
2705 " for (int i = 0; i < n_elements; ++i) {\n"
2706 /*" if (i > 0 && !own_tag && 0 != emb_val &&\n"
2707 " emb_val->embval_index < emb_val->embval_size) {\n"
2708 " emb_val->embval_array->get_embedded_value(emb_val->embval_index).XER_encode(\n"
2709 " UNIVERSAL_CHARSTRING_xer_, p_buf, p_flavor | EMBED_VALUES, p_indent+1, 0);\n"
2710 " ++emb_val->embval_index;\n"
2711 " }\n" - temporarily removed in RT1 */
2712 " ec_1.set_msg(\"%%d: \", i);\n"
2713 " if (e_xer && (p_td.xer_bits & XER_LIST) && i>0) p_buf.put_c(' ');\n"
2714 " value_elements[i].XER_encode(%s_xer_, p_buf, p_flavor, p_indent+own_tag, emb_val);\n"
2716 " if (indenting && !is_exerlist(p_flavor)) {\n",
2717 sdef
->oftypedescrname
2719 if (sdef
->xmlValueList
) {
2720 src
=mputstr(src
, " if (!e_xer) p_buf.put_c('\\n');\n"); /* !e_xer or GDMO */
2723 " do_indent(p_buf, p_indent);\n"
2725 if (sdef
->xerAttribute
) {
2727 " if (e_xer) p_buf.put_c('\\'');\n"
2732 " p_buf.put_c('<');\n"
2733 " p_buf.put_c('/');\n"
2734 " if (e_xer) write_ns_prefix(p_td, p_buf);\n"
2735 " p_buf.put_s((size_t)p_td.namelens[e_xer]-!indenting, (const unsigned char*)p_td.names[e_xer]);\n"
2737 if (sdef
->xerAnyAttrElem
) {
2738 src
= mputstr(src
, " }\n");
2741 " }\n" /* end if(no elements) */
2742 " return (int)p_buf.get_len() - encoded_length;\n"
2746 src
= mputprintf(src
, /* XERSTUFF decoder codegen for record-of */
2748 "// written by %s in " __FILE__
" at %d\n"
2750 "int %s::XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& p_reader, "
2751 "unsigned int p_flavor, embed_values_dec_struct_t* emb_val)\n{\n"
2752 " boolean e_xer = is_exer(p_flavor);\n"
2753 " int xerbits = p_td.xer_bits;\n"
2754 " if (p_flavor & XER_TOPLEVEL) xerbits &= ~UNTAGGED;\n"
2755 " boolean own_tag = !(e_xer && ((xerbits & (ANY_ELEMENT|ANY_ATTRIBUTES|UNTAGGED))"
2756 " || (p_flavor & USE_TYPE_ATTR)));\n" /* incase the parent has USE-UNION */
2757 /* not toplevel anymore and remove the flags for USE-UNION the oftype doesn't need them */
2758 " p_flavor &= ~XER_TOPLEVEL & ~XER_LIST & ~USE_TYPE_ATTR;\n"
2759 " int rd_ok=1, xml_depth=-1;\n"
2760 " *this = NULL_VALUE;\n" /* empty but initialized array */
2761 " int type = 0;\n" /* none */
2762 " if (own_tag) for (rd_ok = p_reader.Ok(); rd_ok == 1; rd_ok = p_reader.Read()) {\n"
2763 " type = p_reader.NodeType();\n"
2764 " if (e_xer && (p_td.xer_bits & XER_ATTRIBUTE)) {\n"
2765 " if ((XML_READER_TYPE_ELEMENT == type && p_reader.MoveToFirstAttribute() == 1)\n"
2766 " || XML_READER_TYPE_ATTRIBUTE == type) {\n"
2767 " verify_name(p_reader, p_td, e_xer);\n"
2771 " if (e_xer && (p_td.xer_bits & XER_LIST)) {\n"
2772 " if (XML_READER_TYPE_TEXT == type) break;\n"
2775 " if (XML_READER_TYPE_ELEMENT == type) {\n"
2776 " verify_name(p_reader, p_td, e_xer);\n"
2777 " xml_depth = p_reader.Depth();\n"
2780 " }\n" /* endif(e_xer && list) */
2781 " }\n" /* next read */
2782 " else xml_depth = p_reader.Depth();\n"
2783 " p_flavor |= XER_RECOF;\n"
2785 , __FUNCTION__
, __LINE__
2790 src
= mputprintf(src
,
2791 " if (e_xer && (p_td.xer_bits & XER_LIST)) {\n" /* LIST decoding*/
2792 " char *x_val = (char*)p_reader.NewValue();\n" /* we own it */
2793 " size_t x_pos = 0;\n"
2794 " size_t x_len = strlen(x_val);\n"
2795 /* The string contains a bunch of values separated by whitespace.
2796 * Tokenize the string and create a new buffer which looks like
2797 * an XML element (<ns:name xmlns:ns='uri'>value</ns:name>),
2798 * then use that to decode the value. */
2799 " for(char * str = strtok(x_val, \" \\t\\x0A\\x0D\"); str != 0; str = strtok(x_val + x_pos, \" \\t\\x0A\\x0D\")) {\n"
2800 // Calling strtok with NULL won't work here, since the decoded element can have strtok calls aswell
2801 " x_pos += strlen(str) + 1;\n"
2802 " TTCN_Buffer buf_2;\n"
2803 " buf_2.put_c('<');\n"
2804 " write_ns_prefix(%s_xer_, buf_2);\n"
2805 " const char * const exer_name = %s_xer_.names[1];\n"
2806 " boolean i_can_has_ns = %s_xer_.my_module != 0 && %s_xer_.ns_index != -1;\n"
2807 /* If it has a namespace, chop off the '>' from the end */
2808 " buf_2.put_s((size_t)%s_xer_.namelens[1]-1-i_can_has_ns, (cbyte*)exer_name);\n"
2809 " if (i_can_has_ns) {\n"
2810 " const namespace_t * const pns = %s_xer_.my_module->get_ns(%s_xer_.ns_index);\n"
2811 " buf_2.put_s(7 - (*pns->px == 0), (cbyte*)\" xmlns:\");\n"
2812 " buf_2.put_s(strlen(pns->px), (cbyte*)pns->px);\n"
2813 " buf_2.put_s(2, (cbyte*)\"='\");\n"
2814 " buf_2.put_s(strlen(pns->ns), (cbyte*)pns->ns);\n"
2815 " buf_2.put_s(2, (cbyte*)\"'>\");\n"
2817 /* start tag completed */
2818 " buf_2.put_s(strlen(str), (cbyte*)str);\n"
2819 " buf_2.put_c('<');\n"
2820 " buf_2.put_c('/');\n"
2821 " write_ns_prefix(%s_xer_, buf_2);\n"
2822 " buf_2.put_s((size_t)%s_xer_.namelens[1], (cbyte*)exer_name);\n"
2823 " XmlReaderWrap reader_2(buf_2);\n"
2824 " rd_ok = reader_2.Read();\n" /* Move to the start element. */
2825 /* Don't move to the #text, that's the callee's responsibility. */
2826 /* The call to the non-const operator[] creates a new element object,
2827 * then we call its XER_decode with the temporary XML reader. */
2828 " (*this)[n_elements].XER_decode(%s_xer_, reader_2, p_flavor, 0);\n"
2829 " if (p_flavor & EXIT_ON_ERROR && !(*this)[n_elements - 1].is_bound()) {\n"
2830 " if (1 == n_elements) {\n"
2831 // Failed to decode even the first element
2834 // Some elements were successfully decoded -> only delete the last one
2835 " set_size(n_elements - 1);\n"
2837 " xmlFree(x_val);\n"
2840 " if (x_pos >= x_len) break;\n"
2842 " xmlFree(x_val);\n"
2843 " if ((p_td.xer_bits & XER_ATTRIBUTE)) ;\n"
2844 /* Let the caller do AdvanceAttribute() */
2845 " else if (own_tag) {\n"
2846 " p_reader.Read();\n" /* on closing tag */
2847 " p_reader.Read();\n" /* past it */
2850 , sdef
->oftypedescrname
, sdef
->oftypedescrname
2851 , sdef
->oftypedescrname
, sdef
->oftypedescrname
2852 , sdef
->oftypedescrname
, sdef
->oftypedescrname
2853 , sdef
->oftypedescrname
, sdef
->oftypedescrname
2854 , sdef
->oftypedescrname
, sdef
->oftypedescrname
2857 src
= mputprintf(src
,
2859 " if (p_flavor & PARENT_CLOSED) ;\n"
2860 /* Nothing to do, but do not advance past the parent's element */
2861 " else if (own_tag && p_reader.IsEmptyElement()) rd_ok = p_reader.Read();\n"
2862 /* It's our XML empty element: nothing to do, skip past it */
2864 /* Note: there is no p_reader.Read() at the end of the loop below.
2865 * Each element is supposed to consume enough to leave the next element
2866 * well-positioned. */
2867 " for (rd_ok = own_tag ? p_reader.Read() : p_reader.Ok(); rd_ok == 1; ) {\n"
2868 " type = p_reader.NodeType();\n"
2869 " if (XML_READER_TYPE_ELEMENT == type)\n"
2871 if (sdef
->xerAnyAttrElem
) {
2872 src
= mputprintf(src
,
2873 " if (e_xer && (p_td.xer_bits & ANY_ELEMENT)) {\n"
2874 /* This is a record-of with ANY-ELEMENT applied, which is really meant
2875 * for the element type (a string), so behave like a record-of
2876 * (string with ANY-ELEMENT): call the non-const operator[]
2877 * to create a new element, then read the entire XML element into it. */
2878 " (*this)[n_elements] = (const char*)p_reader.ReadOuterXml();\n"
2879 /* Consume the element, then move ahead */
2880 " for (rd_ok = p_reader.Read(); rd_ok == 1 && p_reader.Depth() > xml_depth; rd_ok = p_reader.Read()) {}\n"
2881 " if (p_reader.NodeType() != XML_READER_TYPE_ELEMENT) rd_ok = p_reader.Read();\n"
2884 src
= mputprintf(src
,
2886 /* An untagged record-of ends if it encounters an element with a name
2887 * that doesn't match its component */
2888 " if (!own_tag && !can_start((const char*)p_reader.LocalName(), "
2889 "(const char*)p_reader.NamespaceUri(), %s_xer_, p_flavor)) {\n"
2890 " for (; rd_ok == 1 && p_reader.Depth() > xml_depth; rd_ok = p_reader.Read()) ;\n"
2893 /* The call to the non-const operator[] creates the element */
2894 " operator [](n_elements).XER_decode(%s_xer_, p_reader, p_flavor, emb_val);\n"
2895 " if (0 != emb_val && !own_tag && n_elements > 1) {\n"
2896 " ++emb_val->embval_index;\n"
2900 " else if (XML_READER_TYPE_END_ELEMENT == type) {\n"
2901 " for (; p_reader.Depth() > xml_depth; rd_ok = p_reader.Read()) ;\n"
2903 " verify_end(p_reader, p_td, xml_depth, e_xer);\n"
2904 " rd_ok = p_reader.Read();\n" /* move forward one last time */
2908 /*" else if (XML_READER_TYPE_TEXT == type && 0 != emb_val && !own_tag && n_elements > 0) {\n"
2909 " UNIVERSAL_CHARSTRING emb_ustr((const char*)p_reader.Value());\n"
2910 " emb_val->embval_array->set_embedded_value(emb_val->embval_index, emb_ustr);\n"
2911 " rd_ok = p_reader.Read();\n"
2912 " }\n" - temporarily removed in RT1 */
2914 " rd_ok = p_reader.Read();\n"
2916 " }\n" /* next read */
2917 " }\n" /* if not empty element */
2918 " }\n" /* if not LIST */
2921 , sdef
->oftypedescrname
, sdef
->oftypedescrname
2925 // JSON encode, RT1, mem. alloc. optimised
2926 src
= mputprintf(src
,
2927 "int %s::JSON_encode(const TTCN_Typedescriptor_t&, JSON_Tokenizer& p_tok) const\n"
2929 " if (!is_bound()) {\n"
2930 " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND,\n"
2931 " \"Encoding an unbound value of type %s.\");\n"
2934 " int enc_len = p_tok.put_next_token(JSON_TOKEN_ARRAY_START, NULL);\n"
2935 " for(int i = 0; i < n_elements; ++i) {\n"
2936 " int ret_val = value_elements[i].JSON_encode(%s_descr_, p_tok);\n"
2937 " if (0 > ret_val) break;\n"
2938 " enc_len += ret_val;\n"
2940 " enc_len += p_tok.put_next_token(JSON_TOKEN_ARRAY_END, NULL);\n"
2941 " return enc_len;\n"
2943 , name
, dispname
, sdef
->oftypedescrname
);
2945 // JSON decode, RT1, mem. alloc. optimised
2946 src
= mputprintf(src
,
2947 "int %s::JSON_decode(const TTCN_Typedescriptor_t&, JSON_Tokenizer& p_tok, boolean p_silent)\n"
2949 " json_token_t token = JSON_TOKEN_NONE;\n"
2950 " int dec_len = p_tok.get_next_token(&token, NULL, NULL);\n"
2951 " if (JSON_TOKEN_ERROR == token) {\n"
2952 " JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_BAD_TOKEN_ERROR, \"\");\n"
2953 " return JSON_ERROR_FATAL;\n"
2955 " else if (JSON_TOKEN_ARRAY_START != token) {\n"
2956 " return JSON_ERROR_INVALID_TOKEN;\n"
2960 " size_t buf_pos = p_tok.get_buf_pos();\n"
2962 " int ret_val = val.JSON_decode(%s_descr_, p_tok, p_silent);\n"
2963 " if (JSON_ERROR_INVALID_TOKEN == ret_val) {\n"
2964 " p_tok.set_buf_pos(buf_pos);\n"
2967 " else if (JSON_ERROR_FATAL == ret_val) {\n"
2968 " if (p_silent) {\n"
2971 " return JSON_ERROR_FATAL;\n"
2973 " set_size(n_elements + 1);\n"
2974 " value_elements[n_elements - 1] = val;\n"
2975 " dec_len += ret_val;\n"
2977 " dec_len += p_tok.get_next_token(&token, NULL, NULL);\n"
2978 " if (JSON_TOKEN_ARRAY_END != token) {\n"
2979 " JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_REC_OF_END_TOKEN_ERROR, \"\");\n"
2980 " if (p_silent) {\n"
2983 " return JSON_ERROR_FATAL;\n"
2985 " return dec_len;\n"
2987 , name
, type
, sdef
->oftypedescrname
);
2990 def
= mputstr(def
, "};\n\n");
2992 output
->header
.class_decls
= mputprintf(output
->header
.class_decls
,
2993 "class %s;\n", name
);
2994 output
->header
.class_defs
= mputstr(output
->header
.class_defs
, def
);
2996 output
->source
.methods
= mputstr(output
->source
.methods
, src
);
2998 /* Copied from record.c. */
2999 output
->header
.function_prototypes
=
3000 mputprintf(output
->header
.function_prototypes
,
3001 "extern boolean operator==(null_type null_value, const %s& "
3002 "other_value);\n", name
);
3003 output
->source
.function_bodies
=
3004 mputprintf(output
->source
.function_bodies
,
3005 "boolean operator==(null_type, const %s& other_value)\n"
3007 "if (other_value.n_elements==-1)\n"
3008 "TTCN_error(\"The right operand of comparison is an unbound value of "
3010 "return other_value.n_elements == 0;\n"
3011 "}\n\n", name
, dispname
);
3013 output
->header
.function_prototypes
=
3014 mputprintf(output
->header
.function_prototypes
,
3015 "inline boolean operator!=(null_type null_value, const %s& "
3017 "{ return !(null_value == other_value); }\n", name
);
3020 /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
3022 void defRecordOfClass2(const struct_of_def
*sdef
, output_struct
*output
)
3024 char *def
= NULL
, *src
= NULL
;
3025 const char *name
= sdef
->name
;
3026 const char *type
= sdef
->type
;
3027 boolean raw_needed
= sdef
->hasRaw
&& enable_raw();
3028 boolean xer_needed
= sdef
->hasXer
&& enable_xer();
3030 /* Class definition */
3031 def
= mputprintf(def
,
3032 "class %s : public Record_Of_Type {\n", name
);
3034 /* constant unbound element */
3035 def
= mputprintf(def
, "\nstatic const %s UNBOUND_ELEM;\n", type
);
3036 src
= mputprintf(src
, "\nconst %s %s::UNBOUND_ELEM;\n", type
, name
);
3038 /* public member functions */
3039 def
= mputstr(def
, "\npublic:\n");
3042 def
= mputprintf(def
, "%s(): Record_Of_Type() {}\n", name
);
3043 def
= mputprintf(def
, "%s(null_type other_value): Record_Of_Type(other_value) {}\n", name
);
3044 /* copy constructor */
3045 def
= mputprintf(def
, "%s(const %s& other_value): Record_Of_Type(other_value) {}\n", name
, name
);
3047 def
= mputprintf(def
, "~%s() { clean_up(); }\n\n", name
);
3049 /* assignment operators */
3050 def
= mputprintf(def
, "inline %s& operator=(null_type other_value) "
3051 "{ set_val(other_value); return *this; }\n", name
);
3052 def
= mputprintf(def
, "inline %s& operator=(const %s& other_value) "
3053 "{ set_value(&other_value); return *this; }\n\n", name
, name
);
3055 /* comparison operators */
3056 def
= mputprintf(def
, "inline boolean operator==(const %s& other_value) const "
3057 "{ return is_equal(&other_value); }\n", name
);
3058 def
= mputprintf(def
, "boolean operator!=(const %s& other_value) const "
3059 "{ return !is_equal(&other_value); }\n", name
);
3061 /* indexing operators */
3062 def
= mputprintf(def
,
3063 "%s& operator[](int index_value);\n"
3064 "%s& operator[](const INTEGER& index_value);\n"
3065 "const %s& operator[](int index_value) const;\n"
3066 "const %s& operator[](const INTEGER& index_value) const;\n",
3072 src
= mputprintf(src
,
3073 "%s& %s::operator[](int index_value) { return *(static_cast<%s*>(get_at(index_value))); }\n"
3074 "%s& %s::operator[](const INTEGER& index_value) { return *(static_cast<%s*>(get_at(index_value))); }\n"
3075 "const %s& %s::operator[](int index_value) const { return *(static_cast<const %s*>(get_at(index_value))); }\n"
3076 "const %s& %s::operator[](const INTEGER& index_value) const { return *(static_cast<const %s*>(get_at(index_value))); }\n\n",
3082 /* rotation operators */
3083 def
= mputprintf(def
,
3084 "%s operator<<=(int rotate_count) const;\n"
3085 "%s operator<<=(const INTEGER& rotate_count) const;\n"
3086 "%s operator>>=(int rotate_count) const;\n"
3087 "%s operator>>=(const INTEGER& rotate_count) const;\n\n",
3088 name
, name
, name
, name
);
3089 src
= mputprintf(src
,
3090 "%s %s::operator<<=(int rotate_count) const\n"
3092 "return *this >>= (-rotate_count);\n"
3094 "%s %s::operator<<=(const INTEGER& rotate_count) const\n"
3097 "return *((%s*)rotl(rotate_count, &rec_of));\n"
3099 "%s %s::operator>>=(const INTEGER& rotate_count) const\n"
3102 "return *((%s*)rotr(rotate_count, &rec_of));\n"
3104 "%s %s::operator>>=(int rotate_count) const\n"
3107 "return *((%s*)rotr(rotate_count, &rec_of));\n"
3109 name
, name
, name
, name
, name
, name
, name
, name
, name
, name
, name
,
3113 def
= mputprintf(def
,
3114 "%s operator+(const %s& other_value) const;\n\n", name
, name
);
3115 src
= mputprintf(src
,
3116 "%s %s::operator+(const %s& other_value) const\n"
3119 "return *((%s*)concat(&other_value, &rec_of));\n"
3120 "}\n\n", name
, name
, name
, name
, name
);
3123 def
= mputprintf(def
,
3124 "%s substr(int index, int returncount) const;\n\n", name
);
3125 src
= mputprintf(src
,
3126 "%s %s::substr(int index, int returncount) const\n"
3129 "substr_(index, returncount, &rec_of);\n"
3131 "}\n\n", name
, name
, name
);
3134 def
= mputprintf(def
,
3135 "%s replace(int index, int len, const %s& repl) const;\n\n", name
, name
);
3136 src
= mputprintf(src
,
3137 "%s %s::replace(int index, int len, const %s& repl) const\n"
3140 "replace_(index, len, &repl, &rec_of);\n"
3142 "}\n\n", name
, name
, name
, name
);
3143 def
= mputprintf(def
,
3144 "%s replace(int index, int len, const %s_template& repl) const;\n\n",
3146 src
= mputprintf(src
,
3147 "%s %s::replace(int index, int len, const %s_template& repl) const\n"
3150 "replace_(index, len, &repl, &rec_of);\n"
3152 "}\n\n", name
, name
, name
, name
);
3154 def
= mputprintf(def
,
3155 "Base_Type* clone() const { return new %s(*this); }\n"
3156 "const TTCN_Typedescriptor_t* get_descriptor() const;\n"
3157 "const TTCN_Typedescriptor_t* get_elem_descr() const;\n"
3158 "Base_Type* create_elem() const;\n"
3159 "const Base_Type* get_unbound_elem() const;\n"
3160 "boolean is_set() const { return %s; }\n",
3162 (sdef
->kind
== SET_OF
) ? "TRUE" : "FALSE");
3164 src
= mputprintf(src
,
3165 "Base_Type* %s::create_elem() const { return new %s; }\n"
3166 "const Base_Type* %s::get_unbound_elem() const { return &UNBOUND_ELEM; }\n"
3167 "const TTCN_Typedescriptor_t* %s::get_descriptor() const { return &%s_descr_; }\n"
3168 "const TTCN_Typedescriptor_t* %s::get_elem_descr() const { return &%s_descr_; }\n\n",
3172 name
, sdef
->oftypedescrname
);
3174 /* helper functions called by enc/dec members of the ancestor class */
3176 def
= mputprintf(def
, "int rawdec_ebv() const { return %d; }\n",
3177 (int)sdef
->raw
.extension_bit
);
3180 def
= mputprintf(def
, "boolean isXerAttribute() const { return %s; }\n"
3181 "virtual boolean can_start_v(const char * name, const char *uri, "
3182 "XERdescriptor_t const& xd, unsigned int);\n"
3183 "static boolean can_start (const char * name, const char *uri, "
3184 "XERdescriptor_t const& xd, unsigned int);\n",
3185 sdef
->xerAttribute
? "TRUE" : "FALSE");
3186 src
= mputprintf(src
,
3187 /* The virtual can_start_v hands off to the static can_start.
3188 * We must make a virtual call in Record_Of_Type::XER_decode because
3189 * we don't know the actual type (derived from Record_Of_Type) */
3190 "boolean %s::can_start_v(const char *name, const char *uri, "
3191 "XERdescriptor_t const& xd, unsigned int flavor) {\n"
3192 " return can_start(name, uri, xd, flavor);\n"
3194 "boolean %s::can_start(const char *name, const char *uri, "
3195 "XERdescriptor_t const& xd, unsigned int flavor) {\n"
3196 " boolean e_xer = is_exer(flavor);\n"
3197 /* a record-of with ANY-ELEMENT can start with any tag
3198 * :-( with some exceptions )-: */
3199 " if (e_xer && (xd.xer_bits & ANY_ELEMENT)) "
3203 if (sdef
->nFollowers
) {
3205 src
= mputstr(src
, "{\n");
3206 for (f
= 0; f
< sdef
->nFollowers
; ++f
) {
3207 src
= mputprintf(src
,
3208 " if (%s::can_start(name, uri, %s_xer_, flavor)) return FALSE;\n"
3209 , sdef
->followers
[f
].type
3210 , sdef
->followers
[f
].typegen
3218 src
= mputstr(src
, "return TRUE;\n");
3220 src
= mputprintf(src
,
3221 /* if EXER and UNTAGGED, it can begin with the tag of the element,
3222 * otherwise it must be the tag of the type itself,
3223 * specified in the supplied parameter.
3224 * If flavor contains UNTAGGED, that's a signal to go directly
3225 * to the embedded type. */
3226 " if (!e_xer || !((xd.xer_bits|flavor) & UNTAGGED)) return "
3227 "check_name(name, xd, e_xer) && (!e_xer || check_namespace(uri, xd));\n"
3228 " else return %s::can_start(name, uri, %s_xer_, flavor | XER_RECOF);\n"
3229 "}\n\n", sdef
->type
, sdef
->oftypedescrname
);
3230 def
= mputprintf(def
, "boolean isXmlValueList() const { return %s; }\n\n",
3231 sdef
->xmlValueList
? "TRUE" : "FALSE");
3234 /* The call in XER_decode is still there, can_start_v must exist. */
3236 "virtual boolean can_start_v(const char *, const char *, "
3237 "XERdescriptor_t const&, unsigned int) { return FALSE; }\n");
3241 def
= mputstr(def
, "};\n\n");
3243 output
->header
.class_decls
= mputprintf(output
->header
.class_decls
,
3244 "class %s;\n", name
);
3245 output
->header
.class_defs
= mputstr(output
->header
.class_defs
, def
);
3247 output
->source
.methods
= mputstr(output
->source
.methods
, src
);
3251 /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
3253 void defRecordOfTemplate1(const struct_of_def
*sdef
, output_struct
*output
)
3255 char *def
= NULL
, *src
= NULL
;
3256 const char *name
= sdef
->name
, *dispname
= sdef
->dispname
;
3257 const char *type
= sdef
->type
;
3258 const char *base_class
= sdef
->kind
== RECORD_OF
? "Record_Of_Template" :
3259 "Restricted_Length_Template";
3261 /* Class definition and private data members */
3262 def
= mputprintf(def
,
3263 "class %s_template : public %s {\n"
3267 "%s_template **value_elements;\n"
3270 "unsigned int n_values;\n"
3271 "%s_template *list_value;\n"
3272 "} value_list;\n", name
, base_class
, type
, name
);
3273 if (sdef
->kind
== SET_OF
) {
3274 def
= mputprintf(def
,
3276 "unsigned int n_items;\n"
3277 "%s_template *set_items;\n"
3278 "} value_set;\n", type
);
3280 def
= mputstr(def
, "};\n");
3282 /* private member functions */
3284 /* copy_value function */
3285 def
= mputprintf(def
, "void copy_value(const %s& other_value);\n", name
);
3286 src
= mputprintf(src
,
3287 "void %s_template::copy_value(const %s& other_value)\n"
3289 "if (!other_value.is_bound()) "
3290 "TTCN_error(\"Initialization of a template of type %s with an unbound "
3292 "single_value.n_elements = other_value.size_of();\n"
3293 "single_value.value_elements = "
3294 "(%s_template**)allocate_pointers(single_value.n_elements);\n"
3295 "for (int elem_count = 0; elem_count < single_value.n_elements; "
3297 "if (other_value[elem_count].is_bound()) {\n"
3298 "single_value.value_elements[elem_count] = "
3299 "new %s_template(other_value[elem_count]);\n"
3301 "single_value.value_elements[elem_count] = new %s_template;\n"
3304 "set_selection(SPECIFIC_VALUE);\n"
3305 "}\n\n", name
, name
, dispname
, type
, type
, type
);
3307 /* copy_template function */
3308 def
= mputprintf(def
, "void copy_template(const %s_template& "
3309 "other_value);\n", name
);
3310 src
= mputprintf(src
,
3311 "void %s_template::copy_template(const %s_template& other_value)\n"
3313 "switch (other_value.template_selection) {\n"
3314 "case SPECIFIC_VALUE:\n"
3315 "single_value.n_elements = other_value.single_value.n_elements;\n"
3316 "single_value.value_elements = "
3317 "(%s_template**)allocate_pointers(single_value.n_elements);\n"
3318 "for (int elem_count = 0; elem_count < single_value.n_elements; "
3320 "if (UNINITIALIZED_TEMPLATE != "
3321 "other_value.single_value.value_elements[elem_count]->get_selection()) {\n"
3322 "single_value.value_elements[elem_count] = new %s_template"
3323 "(*other_value.single_value.value_elements[elem_count]);\n"
3325 "single_value.value_elements[elem_count] = new %s_template;\n"
3328 "case OMIT_VALUE:\n"
3330 "case ANY_OR_OMIT:\n"
3332 "case VALUE_LIST:\n"
3333 "case COMPLEMENTED_LIST:\n"
3334 "value_list.n_values = other_value.value_list.n_values;\n"
3335 "value_list.list_value = new %s_template[value_list.n_values];\n"
3336 "for (unsigned int list_count = 0; list_count < value_list.n_values; "
3338 "value_list.list_value[list_count].copy_template("
3339 "other_value.value_list.list_value[list_count]);\n"
3340 "break;\n", name
, name
, type
, type
, type
, name
);
3341 if (sdef
->kind
== SET_OF
) {
3342 src
= mputprintf(src
,
3343 "case SUPERSET_MATCH:\n"
3344 "case SUBSET_MATCH:\n"
3345 "value_set.n_items = other_value.value_set.n_items;\n"
3346 "value_set.set_items = new %s_template[value_set.n_items];\n"
3347 "for (unsigned int set_count = 0; set_count < value_set.n_items; "
3349 "value_set.set_items[set_count] = "
3350 "other_value.value_set.set_items[set_count];\n"
3353 src
= mputprintf(src
,
3355 "TTCN_error(\"Copying an uninitialized/unsupported template of type "
3359 "set_selection(other_value);\n"
3362 /* callback function for matching specific values */
3364 "static boolean match_function_specific(const Base_Type *value_ptr, "
3365 "int value_index, const Restricted_Length_Template *template_ptr, "
3366 "int template_index);\n");
3367 src
= mputprintf(src
,
3368 "boolean %s_template::match_function_specific(const Base_Type *value_ptr, "
3369 "int value_index, const Restricted_Length_Template *template_ptr, "
3370 "int template_index)\n"
3372 "if (value_index >= 0) return ((const %s_template*)template_ptr)->"
3373 "single_value.value_elements[template_index]->"
3374 "match((*(const %s*)value_ptr)[value_index]);\n"
3375 "else return ((const %s_template*)template_ptr)->"
3376 "single_value.value_elements[template_index]->is_any_or_omit();\n"
3377 "}\n\n", name
, name
, name
, name
);
3379 if (sdef
->kind
== SET_OF
) {
3380 /* callback function for matching superset and subset */
3382 "static boolean match_function_set(const Base_Type *value_ptr, "
3383 "int value_index, const Restricted_Length_Template *template_ptr, "
3384 "int template_index);\n");
3385 src
= mputprintf(src
,
3386 "boolean %s_template::match_function_set(const Base_Type *value_ptr, "
3387 "int value_index, const Restricted_Length_Template *template_ptr, "
3388 "int template_index)\n"
3390 "if (value_index >= 0) return ((const %s_template*)template_ptr)->"
3391 "value_set.set_items[template_index].match("
3392 "(*(const %s*)value_ptr)[value_index]);\n"
3393 "else return ((const %s_template*)template_ptr)->"
3394 "value_set.set_items[template_index].is_any_or_omit();\n"
3395 "}\n\n", name
, name
, name
, name
);
3397 /* callback function for log_match_heuristics */
3399 "static void log_function(const Base_Type *value_ptr, "
3400 "const Restricted_Length_Template *template_ptr,"
3401 " int index_value, int index_template);\n");
3402 src
= mputprintf(src
,
3403 "void %s_template::log_function(const Base_Type *value_ptr, "
3404 "const Restricted_Length_Template *template_ptr,"
3405 " int index_value, int index_template)\n"
3407 "if (value_ptr != NULL && template_ptr != NULL)"
3408 "((const %s_template*)template_ptr)"
3409 "->single_value.value_elements[index_template]"
3410 "->log_match((*(const %s*)value_ptr)[index_value]);\n"
3411 "else if (value_ptr != NULL) (*(const %s*)value_ptr)[index_value].log();\n"
3412 "else if (template_ptr != NULL) ((const %s_template*)template_ptr)"
3413 "->single_value.value_elements[index_template]->log();\n"
3414 "}\n\n", name
, name
, name
, name
, name
);
3417 /* public member functions */
3418 def
= mputstr(def
, "\npublic:\n");
3421 def
= mputprintf(def
, "%s_template();\n", name
);
3422 src
= mputprintf(src
, "%s_template::%s_template()\n"
3424 "}\n\n", name
, name
);
3426 def
= mputprintf(def
, "%s_template(template_sel other_value);\n", name
);
3427 src
= mputprintf(src
, "%s_template::%s_template(template_sel other_value)\n"
3428 " : %s(other_value)\n"
3430 "check_single_selection(other_value);\n"
3431 "}\n\n", name
, name
, base_class
);
3433 def
= mputprintf(def
, "%s_template(null_type other_value);\n", name
);
3434 src
= mputprintf(src
, "%s_template::%s_template(null_type)\n"
3435 " : %s(SPECIFIC_VALUE)\n"
3437 "single_value.n_elements = 0;\n"
3438 "single_value.value_elements = NULL;\n"
3439 "}\n\n", name
, name
, base_class
);
3441 def
= mputprintf(def
, "%s_template(const %s& other_value);\n", name
, name
);
3442 src
= mputprintf(src
, "%s_template::%s_template(const %s& other_value)\n"
3444 "copy_value(other_value);\n"
3445 "}\n\n", name
, name
, name
);
3447 def
= mputprintf(def
, "%s_template(const OPTIONAL<%s>& other_value);\n",
3449 src
= mputprintf(src
,
3450 "%s_template::%s_template(const OPTIONAL<%s>& other_value)\n"
3452 "switch (other_value.get_selection()) {\n"
3453 "case OPTIONAL_PRESENT:\n"
3454 "copy_value((const %s&)other_value);\n"
3456 "case OPTIONAL_OMIT:\n"
3457 "set_selection(OMIT_VALUE);\n"
3460 "TTCN_error(\"Creating a template of type %s from an unbound optional "
3463 "}\n\n", name
, name
, name
, name
, dispname
);
3465 /* copy constructor */
3466 def
= mputprintf(def
, "%s_template(const %s_template& other_value);\n",
3468 src
= mputprintf(src
,
3469 "%s_template::%s_template(const %s_template& other_value)\n"
3472 "copy_template(other_value);\n"
3473 "}\n\n", name
, name
, name
, base_class
);
3476 def
= mputprintf(def
, "~%s_template();\n\n", name
);
3477 src
= mputprintf(src
,
3478 "%s_template::~%s_template()\n"
3481 "}\n\n", name
, name
);
3483 /* clean_up function */
3484 def
= mputstr(def
, "void clean_up();\n");
3485 src
= mputprintf(src
,
3486 "void %s_template::clean_up()\n"
3488 "switch (template_selection) {\n"
3489 "case SPECIFIC_VALUE:\n"
3490 "for (int elem_count = 0; elem_count < single_value.n_elements; "
3492 "delete single_value.value_elements[elem_count];\n"
3493 "free_pointers((void**)single_value.value_elements);\n"
3495 "case VALUE_LIST:\n"
3496 "case COMPLEMENTED_LIST:\n"
3497 "delete [] value_list.list_value;\n", name
);
3498 if (sdef
->kind
== SET_OF
) {
3501 "case SUPERSET_MATCH:\n"
3502 "case SUBSET_MATCH:\n"
3503 "delete [] value_set.set_items;\n");
3509 "template_selection = UNINITIALIZED_TEMPLATE;\n"
3512 /* assignment operators */
3513 def
= mputprintf(def
, "%s_template& operator=(template_sel other_value);\n",
3515 src
= mputprintf(src
,
3516 "%s_template& %s_template::operator=(template_sel other_value)\n"
3518 "check_single_selection(other_value);\n"
3520 "set_selection(other_value);\n"
3522 "}\n\n", name
, name
);
3524 def
= mputprintf(def
, "%s_template& operator=(null_type other_value);\n",
3526 src
= mputprintf(src
,
3527 "%s_template& %s_template::operator=(null_type)\n"
3530 "set_selection(SPECIFIC_VALUE);\n"
3531 "single_value.n_elements = 0;\n"
3532 "single_value.value_elements = NULL;\n"
3534 "}\n\n", name
, name
);
3536 def
= mputprintf(def
, "%s_template& operator=(const %s& other_value);\n",
3538 src
= mputprintf(src
,
3539 "%s_template& %s_template::operator=(const %s& other_value)\n"
3542 "copy_value(other_value);\n"
3544 "}\n\n", name
, name
, name
);
3546 def
= mputprintf(def
, "%s_template& operator=(const OPTIONAL<%s>& "
3547 "other_value);\n", name
, name
);
3548 src
= mputprintf(src
,
3549 "%s_template& %s_template::operator=(const OPTIONAL<%s>& other_value)\n"
3552 "switch (other_value.get_selection()) {\n"
3553 "case OPTIONAL_PRESENT:\n"
3554 "copy_value((const %s&)other_value);\n"
3556 "case OPTIONAL_OMIT:\n"
3557 "set_selection(OMIT_VALUE);\n"
3560 "TTCN_error(\"Assignment of an unbound optional field to a template of "
3564 "}\n\n", name
, name
, name
, name
, dispname
);
3566 def
= mputprintf(def
, "%s_template& operator=(const %s_template& "
3567 "other_value);\n\n", name
, name
);
3568 src
= mputprintf(src
,
3569 "%s_template& %s_template::operator=(const %s_template& other_value)\n"
3571 "if (&other_value != this) {\n"
3573 "copy_template(other_value);\n"
3576 "}\n\n", name
, name
, name
);
3578 /* indexing operators */
3579 /* Non-const operator[] is allowed to extend */
3580 def
= mputprintf(def
, "%s_template& operator[](int index_value);\n", type
);
3581 src
= mputprintf(src
,
3582 "%s_template& %s_template::operator[](int index_value)\n"
3584 "if (index_value < 0) TTCN_error(\"Accessing an element of a template "
3585 "for type %s using a negative index: %%d.\", index_value);\n"
3586 "switch (template_selection)\n"
3588 " case SPECIFIC_VALUE:\n"
3589 " if(index_value < single_value.n_elements) break;\n"
3591 " case OMIT_VALUE:\n"
3592 " case ANY_VALUE:\n"
3593 " case ANY_OR_OMIT:\n"
3594 " case UNINITIALIZED_TEMPLATE:\n"
3595 " set_size(index_value + 1);\n"
3598 " TTCN_error(\"Accessing an "
3599 "element of a non-specific template for type %s.\");\n"
3602 "return *single_value.value_elements[index_value];\n"
3603 "}\n\n", type
, name
, dispname
, dispname
);
3605 def
= mputprintf(def
, "%s_template& operator[](const INTEGER& "
3606 "index_value);\n", type
);
3607 src
= mputprintf(src
,
3608 "%s_template& %s_template::operator[](const INTEGER& index_value)\n"
3610 "index_value.must_bound(\"Using an unbound integer value for indexing "
3611 "a template of type %s.\");\n"
3612 "return (*this)[(int)index_value];\n"
3613 "}\n\n", type
, name
, dispname
);
3615 /* Const operator[] throws an error if over-indexing */
3616 def
= mputprintf(def
, "const %s_template& operator[](int index_value) "
3618 src
= mputprintf(src
,
3619 "const %s_template& %s_template::operator[](int index_value) const\n"
3621 "if (index_value < 0) TTCN_error(\"Accessing an element of a template "
3622 "for type %s using a negative index: %%d.\", index_value);\n"
3623 "if (template_selection != SPECIFIC_VALUE) TTCN_error(\"Accessing an "
3624 "element of a non-specific template for type %s.\");\n"
3625 "if (index_value >= single_value.n_elements) "
3626 "TTCN_error(\"Index overflow in a template of type %s: "
3627 "The index is %%d, but the template has only %%d elements.\", "
3628 "index_value, single_value.n_elements);\n"
3629 "return *single_value.value_elements[index_value];\n"
3630 "}\n\n", type
, name
, dispname
, dispname
, dispname
);
3632 def
= mputprintf(def
, "const %s_template& operator[](const INTEGER& "
3633 "index_value) const;\n\n", type
);
3634 src
= mputprintf(src
,
3635 "const %s_template& %s_template::operator[](const INTEGER& index_value) "
3638 "index_value.must_bound(\"Using an unbound integer value for indexing "
3639 "a template of type %s.\");\n"
3640 "return (*this)[(int)index_value];\n"
3641 "}\n\n", type
, name
, dispname
);
3643 /* set_size function */
3644 def
= mputstr(def
, "void set_size(int new_size);\n");
3645 src
= mputprintf(src
, "void %s_template::set_size(int new_size)\n"
3647 "if (new_size < 0) TTCN_error(\"Internal error: Setting a negative size "
3648 "for a template of type %s.\");\n"
3649 "template_sel old_selection = template_selection;\n"
3650 "if (old_selection != SPECIFIC_VALUE) {\n"
3652 "set_selection(SPECIFIC_VALUE);\n"
3653 "single_value.n_elements = 0;\n"
3654 "single_value.value_elements = NULL;\n"
3656 "if (new_size > single_value.n_elements) {\n"
3657 "single_value.value_elements = (%s_template**)reallocate_pointers((void**)"
3658 "single_value.value_elements, single_value.n_elements, new_size);\n"
3659 "if (old_selection == ANY_VALUE || old_selection == ANY_OR_OMIT) {\n"
3660 "for (int elem_count = single_value.n_elements; elem_count < new_size; "
3662 "single_value.value_elements[elem_count] = new %s_template(ANY_VALUE);\n"
3664 "for (int elem_count = single_value.n_elements; elem_count < new_size; "
3666 "single_value.value_elements[elem_count] = new %s_template;\n"
3668 "single_value.n_elements = new_size;\n"
3669 "} else if (new_size < single_value.n_elements) {\n"
3670 "for (int elem_count = new_size; elem_count < single_value.n_elements; "
3672 "delete single_value.value_elements[elem_count];\n"
3673 "single_value.value_elements = (%s_template**)reallocate_pointers((void**)"
3674 "single_value.value_elements, single_value.n_elements, new_size);\n"
3675 "single_value.n_elements = new_size;\n"
3677 "}\n\n", name
, dispname
, type
, type
, type
, type
);
3680 def
= mputstr(def
, "int n_elem() const;\n");
3681 src
= mputprintf(src
,
3682 "int %s_template::n_elem() const\n"
3684 " switch (template_selection) {\n"
3685 " case SPECIFIC_VALUE:\n"
3686 " return single_value.n_elements;\n"
3688 " case VALUE_LIST:\n"
3689 " return value_list.n_values;\n"
3691 /* if (sdef->kind == SET_OF) {
3692 src = mputprintf(src,
3695 src
= mputstr(src
, " default:\n"
3696 " TTCN_error(\"Performing n_elem\");\n"
3701 /* sizeof operation */
3703 "int size_of(boolean is_size) const;\n"
3704 "inline int size_of() const { return size_of(TRUE); }\n"
3705 "inline int lengthof() const { return size_of(FALSE); }\n"
3707 src
= mputprintf(src
,
3708 "int %s_template::size_of(boolean is_size) const\n"
3710 "const char* op_name = is_size ? \"size\" : \"length\";\n"
3712 "boolean has_any_or_none;\n"
3713 "if (is_ifpresent) TTCN_error(\"Performing %%sof() operation on a "
3714 "template of type %s which has an ifpresent attribute.\", op_name);\n"
3715 "switch (template_selection)\n"
3717 "case SPECIFIC_VALUE: {\n"
3719 " has_any_or_none = FALSE;\n"
3720 " int elem_count = single_value.n_elements;\n"
3721 " if (!is_size) { while (elem_count>0 && !single_value.value_elements"
3722 "[elem_count-1]->is_bound()) elem_count--; }\n"
3723 " for (int i=0; i<elem_count; i++) {\n"
3724 " switch (single_value.value_elements[i]->get_selection()) {\n"
3725 " case OMIT_VALUE:\n"
3726 " TTCN_error(\"Performing %%sof() operation on a template of type "
3727 "%s containing omit element.\", op_name);\n"
3728 " case ANY_OR_OMIT:\n"
3729 " has_any_or_none = TRUE;\n"
3737 name
, dispname
, dispname
);
3738 if (sdef
->kind
== SET_OF
) {
3739 src
= mputprintf(src
,
3740 "case SUPERSET_MATCH:\n"
3741 "case SUBSET_MATCH: {\n"
3743 " has_any_or_none = FALSE;\n"
3744 " int elem_count = value_set.n_items;\n"
3745 " if (!is_size) { while (elem_count>0 && !value_set.set_items"
3746 "[elem_count-1].is_bound()) elem_count--; }\n"
3747 " for (int i=0; i<elem_count; i++) {\n"
3748 " switch (value_set.set_items[i].get_selection())\n"
3750 " case OMIT_VALUE:\n"
3751 " TTCN_error(\"Performing %%sof() operation on a template of type "
3752 "%s containing omit element.\", op_name);\n"
3753 " case ANY_OR_OMIT:\n"
3754 " has_any_or_none = TRUE;\n"
3761 " if (template_selection==SUPERSET_MATCH) {\n"
3762 " has_any_or_none = TRUE;\n"
3764 " int max_size = min_size;\n"
3766 " if (!has_any_or_none) { // [0,max_size]\n"
3767 " switch (length_restriction_type) {\n"
3768 " case NO_LENGTH_RESTRICTION:\n"
3769 " if (max_size==0) return 0;\n"
3770 " TTCN_error(\"Performing %%sof() operation on a template of "
3771 "type %s with no exact size.\", op_name);\n"
3772 " case SINGLE_LENGTH_RESTRICTION:\n"
3773 " if (length_restriction.single_length<=max_size)\n"
3774 " return length_restriction.single_length;\n"
3775 " TTCN_error(\"Performing %%sof() operation on an invalid "
3776 "template of type %s. The maximum size (%%d) contradicts the length "
3777 "restriction (%%d).\", op_name, max_size, "
3778 "length_restriction.single_length);\n"
3779 " case RANGE_LENGTH_RESTRICTION:\n"
3780 " if (max_size==length_restriction.range_length.min_length) {\n"
3781 " return max_size;\n"
3782 " } else if (max_size>length_restriction.range_length.min_length)"
3784 " TTCN_error(\"Performing %%sof() operation on a template of "
3785 "type %s with no exact size.\", op_name);\n"
3787 " TTCN_error(\"Performing %%sof() operation on an invalid "
3788 "template of type %s. Maximum size (%%d) contradicts the length "
3789 "restriction (%%d..%%d).\", op_name, max_size, "
3790 "length_restriction.range_length.min_length, "
3791 "length_restriction.range_length.max_length);\n"
3793 " TTCN_error(\"Internal error: Template has invalid length "
3794 "restriction type.\");\n"
3799 dispname
, dispname
, dispname
, dispname
, dispname
);
3801 src
= mputprintf(src
,
3802 "case OMIT_VALUE:\n"
3803 " TTCN_error(\"Performing %%sof() operation on a template of type %s "
3804 "containing omit value.\", op_name);\n"
3806 "case ANY_OR_OMIT:\n"
3808 " has_any_or_none = TRUE;\n"
3810 "case VALUE_LIST:\n"
3812 " if (value_list.n_values<1)\n"
3813 " TTCN_error(\"Performing %%sof() operation on a "
3814 "template of type %s containing an empty list.\", op_name);\n"
3815 " int item_size = value_list.list_value[0].size_of(is_size);\n"
3816 " for (unsigned int i = 1; i < value_list.n_values; i++) {\n"
3817 " if (value_list.list_value[i].size_of(is_size)!=item_size)\n"
3818 " TTCN_error(\"Performing %%sof() operation on a template of type "
3819 "%s containing a value list with different sizes.\", op_name);\n"
3821 " min_size = item_size;\n"
3822 " has_any_or_none = FALSE;\n"
3825 "case COMPLEMENTED_LIST:\n"
3826 " TTCN_error(\"Performing %%sof() operation on a template of type %s "
3827 "containing complemented list.\", op_name);\n"
3829 " TTCN_error(\"Performing %%sof() operation on an "
3830 "uninitialized/unsupported template of type %s.\", op_name);\n"
3832 "return check_section_is_single(min_size, has_any_or_none, "
3833 "op_name, \"a\", \"template of type %s\");\n"
3835 dispname
, dispname
, dispname
, dispname
, dispname
, dispname
);
3837 /* match operation */
3838 def
= mputprintf(def
, "boolean match(const %s& other_value) const;\n",
3840 src
= mputprintf(src
,
3841 "boolean %s_template::match(const %s& other_value) const\n"
3843 "if (!other_value.is_bound()) return FALSE;\n"
3844 "int value_length = other_value.size_of();\n"
3845 "if (!match_length(value_length)) return FALSE;\n"
3846 "switch (template_selection) {\n"
3847 "case SPECIFIC_VALUE:\n"
3848 "return match_%s_of(&other_value, value_length, this, "
3849 "single_value.n_elements, match_function_specific);\n"
3850 "case OMIT_VALUE:\n"
3853 "case ANY_OR_OMIT:\n"
3855 "case VALUE_LIST:\n"
3856 "case COMPLEMENTED_LIST:\n"
3857 "for (unsigned int list_count = 0; list_count < value_list.n_values; "
3859 "if (value_list.list_value[list_count].match(other_value)) "
3860 "return template_selection == VALUE_LIST;\n"
3861 "return template_selection == COMPLEMENTED_LIST;\n",
3862 name
, name
, sdef
->kind
== RECORD_OF
? "record" : "set");
3863 if (sdef
->kind
== SET_OF
) {
3865 "case SUPERSET_MATCH:\n"
3866 "case SUBSET_MATCH:\n"
3867 "return match_set_of(&other_value, value_length, this, "
3868 "value_set.n_items, match_function_set);\n");
3870 src
= mputprintf(src
,
3872 "TTCN_error(\"Matching with an uninitialized/unsupported template "
3878 /* is_bound function */
3880 "inline boolean is_bound() const \n"
3881 " {return template_selection != UNINITIALIZED_TEMPLATE; }\n");
3883 /* is_value operation */
3884 def
= mputstr(def
, "boolean is_value() const;\n");
3885 src
= mputprintf(src
,
3886 "boolean %s_template::is_value() const\n"
3888 "if (template_selection != SPECIFIC_VALUE || is_ifpresent) return false;\n"
3889 "for (int elem_count = 0; elem_count < single_value.n_elements; "
3891 "if (!single_value.value_elements[elem_count]->is_value()) return false;\n"
3895 /* valueof operation */
3896 def
= mputprintf(def
, "%s valueof() const;\n", name
);
3897 src
= mputprintf(src
,
3898 "%s %s_template::valueof() const\n"
3900 "if (template_selection != SPECIFIC_VALUE || is_ifpresent) TTCN_error(\""
3901 "Performing a valueof or send operation on a non-specific template of type "
3904 "ret_val.set_size(single_value.n_elements);\n"
3905 "for (int elem_count = 0; elem_count < single_value.n_elements; "
3907 "if (single_value.value_elements[elem_count]->is_bound()) {\n"
3908 "ret_val[elem_count] = single_value.value_elements[elem_count]->valueof();\n"
3911 "}\n\n", name
, name
, dispname
, name
);
3913 /* substr() predefined function for templates */
3914 def
= mputprintf(def
,
3915 "%s substr(int index, int returncount) const;\n\n", name
);
3916 src
= mputprintf(src
,
3917 "%s %s_template::substr(int index, int returncount) const\n"
3919 "if (!is_value()) TTCN_error(\"The first argument of function substr() is "
3920 "a template with non-specific value.\");\n"
3921 "return valueof().substr(index, returncount);\n"
3922 "}\n\n", name
, name
);
3924 /* replace() predefined function for templates */
3925 def
= mputprintf(def
,
3926 "%s replace(int index, int len, const %s_template& repl) const;\n\n", name
, name
);
3927 src
= mputprintf(src
,
3928 "%s %s_template::replace(int index, int len, const %s_template& repl) const\n"
3930 "if (!is_value()) TTCN_error(\"The first argument of function replace() is "
3931 "a template with non-specific value.\");\n"
3932 "if (!repl.is_value()) TTCN_error(\"The fourth argument of function "
3933 "replace() is a template with non-specific value.\");\n"
3934 "return valueof().replace(index, len, repl.valueof());\n"
3935 "}\n\n", name
, name
, name
);
3936 def
= mputprintf(def
,
3937 "%s replace(int index, int len, const %s& repl) const;\n\n", name
, name
);
3938 src
= mputprintf(src
,
3939 "%s %s_template::replace(int index, int len, const %s& repl) const\n"
3941 "if (!is_value()) TTCN_error(\"The first argument of function replace() is "
3942 "a template with non-specific value.\");\n"
3943 "return valueof().replace(index, len, repl);\n"
3944 "}\n\n", name
, name
, name
);
3946 /* value list and set handling operators */
3948 "void set_type(template_sel template_type, unsigned int list_length);\n");
3949 src
= mputprintf(src
,
3950 "void %s_template::set_type(template_sel template_type, "
3951 "unsigned int list_length)\n"
3954 "switch (template_type) {\n"
3955 "case VALUE_LIST:\n"
3956 "case COMPLEMENTED_LIST:\n"
3957 "value_list.n_values = list_length;\n"
3958 "value_list.list_value = new %s_template[list_length];\n"
3959 "break;\n", name
, name
);
3960 if (sdef
->kind
== SET_OF
) {
3961 src
= mputprintf(src
,
3962 "case SUPERSET_MATCH:\n"
3963 "case SUBSET_MATCH:\n"
3964 "value_set.n_items = list_length;\n"
3965 "value_set.set_items = new %s_template[list_length];\n"
3968 src
= mputprintf(src
,
3970 "TTCN_error(\"Internal error: Setting an invalid type for a template of "
3973 "set_selection(template_type);\n"
3976 def
= mputprintf(def
,
3977 "%s_template& list_item(unsigned int list_index);\n", name
);
3978 src
= mputprintf(src
,
3979 "%s_template& %s_template::list_item(unsigned int list_index)\n"
3981 "if (template_selection != VALUE_LIST && "
3982 "template_selection != COMPLEMENTED_LIST) "
3983 "TTCN_error(\"Internal error: Accessing a list element of a non-list "
3984 "template of type %s.\");\n"
3985 "if (list_index >= value_list.n_values) "
3986 "TTCN_error(\"Internal error: Index overflow in a value list template "
3988 "return value_list.list_value[list_index];\n"
3989 "}\n\n", name
, name
, dispname
, dispname
);
3991 if (sdef
->kind
== SET_OF
) {
3992 def
= mputprintf(def
,
3993 "%s_template& set_item(unsigned int set_index);\n", type
);
3994 src
= mputprintf(src
,
3995 "%s_template& %s_template::set_item(unsigned int set_index)\n"
3997 "if (template_selection != SUPERSET_MATCH && "
3998 "template_selection != SUBSET_MATCH) "
3999 "TTCN_error(\"Internal error: Accessing a set element of a non-set "
4000 "template of type %s.\");\n"
4001 "if (set_index >= value_set.n_items) "
4002 "TTCN_error(\"Internal error: Index overflow in a set template of "
4004 "return value_set.set_items[set_index];\n"
4005 "}\n\n", type
, name
, dispname
, dispname
);
4008 /* logging functions */
4009 def
= mputstr(def
, "void log() const;\n");
4012 "void %s_template::log() const\n"
4014 "switch (template_selection) {\n"
4015 "case SPECIFIC_VALUE:\n"
4016 "if (single_value.n_elements > 0) {\n"
4017 "TTCN_Logger::log_event_str(\"{ \");\n"
4018 "for (int elem_count = 0; elem_count < single_value.n_elements; "
4020 "if (elem_count > 0) TTCN_Logger::log_event_str(\", \");\n", name
);
4021 if (sdef
->kind
== RECORD_OF
) {
4023 "if (permutation_starts_at(elem_count)) "
4024 "TTCN_Logger::log_event_str(\"permutation(\");\n");
4026 src
= mputstr(src
, "single_value.value_elements[elem_count]->log();\n");
4027 if (sdef
->kind
== RECORD_OF
) {
4029 "if (permutation_ends_at(elem_count)) TTCN_Logger::log_char(')');\n");
4033 "TTCN_Logger::log_event_str(\" }\");\n"
4034 "} else TTCN_Logger::log_event_str(\"{ }\");\n"
4036 "case COMPLEMENTED_LIST:\n"
4037 "TTCN_Logger::log_event_str(\"complement\");\n"
4038 "case VALUE_LIST:\n"
4039 "TTCN_Logger::log_char('(');\n"
4040 "for (unsigned int list_count = 0; list_count < value_list.n_values; "
4042 "if (list_count > 0) TTCN_Logger::log_event_str(\", \");\n"
4043 "value_list.list_value[list_count].log();\n"
4045 "TTCN_Logger::log_char(')');\n"
4047 if (sdef
->kind
== SET_OF
) {
4049 "case SUPERSET_MATCH:\n"
4050 "case SUBSET_MATCH:\n"
4051 "TTCN_Logger::log_event(\"%s(\", template_selection == SUPERSET_MATCH "
4052 "? \"superset\" : \"subset\");\n"
4053 "for (unsigned int set_count = 0; set_count < value_set.n_items; "
4055 "if (set_count > 0) TTCN_Logger::log_event_str(\", \");\n"
4056 "value_set.set_items[set_count].log();\n"
4058 "TTCN_Logger::log_char(')');\n"
4065 "log_restricted();\n"
4066 "log_ifpresent();\n"
4069 def
= mputprintf(def
, "void log_match(const %s& match_value) const;\n",
4071 src
= mputprintf(src
, "void %s_template::log_match(const %s& match_value) "
4074 "if(TTCN_Logger::VERBOSITY_COMPACT == TTCN_Logger::get_matching_verbosity()){\n"
4075 "if(match(match_value)){\n"
4076 "TTCN_Logger::print_logmatch_buffer();\n"
4077 "TTCN_Logger::log_event_str(\" matched\");\n"
4078 "}else{\n", name
, name
);
4080 if (sdef
->kind
== RECORD_OF
) {
4082 "if (template_selection == SPECIFIC_VALUE && "
4083 "single_value.n_elements > 0 && get_number_of_permutations() == 0 && "
4084 "single_value.n_elements == match_value.size_of()) {\n"
4085 "size_t previous_size = TTCN_Logger::get_logmatch_buffer_len();\n"
4086 "for (int elem_count = 0; elem_count < single_value.n_elements; "
4088 "if(!single_value.value_elements[elem_count]->match(match_value[elem_count])){\n"
4089 "TTCN_Logger::log_logmatch_info(\"[%d]\", elem_count);\n"
4090 "single_value.value_elements[elem_count]->log_match(match_value[elem_count]);\n"
4091 "TTCN_Logger::set_logmatch_buffer_len(previous_size);\n"
4094 "log_match_length(single_value.n_elements);\n"
4096 "TTCN_Logger::print_logmatch_buffer();\n"
4097 "match_value.log();\n"
4098 "TTCN_Logger::log_event_str(\" with \");\n"
4100 "TTCN_Logger::log_event_str(\" unmatched\");\n"
4103 if (sdef
->kind
== SET_OF
) {
4105 "size_t previous_size = TTCN_Logger::get_logmatch_buffer_len();\n"
4106 "if (template_selection == SPECIFIC_VALUE)\n"
4107 " log_match_heuristics(&match_value, match_value.size_of(), this, "
4108 "single_value.n_elements, match_function_specific, log_function);\n"
4110 "if(previous_size != 0){\n"
4111 "TTCN_Logger::print_logmatch_buffer();\n"
4112 "TTCN_Logger::set_logmatch_buffer_len(previous_size);\n"
4113 "TTCN_Logger::log_event_str(\":=\");\n"
4116 "match_value.log();\n"
4117 "TTCN_Logger::log_event_str(\" with \");\n"
4119 "TTCN_Logger::log_event_str(\" unmatched\");\n"
4123 src
= mputstr(src
, "}\n"
4126 if (sdef
->kind
== RECORD_OF
) {
4127 /* logging by element is meaningful for 'record of' only */
4129 "if (template_selection == SPECIFIC_VALUE && "
4130 "single_value.n_elements > 0 && get_number_of_permutations() == 0 && "
4131 "single_value.n_elements == match_value.size_of()) {\n"
4132 "TTCN_Logger::log_event_str(\"{ \");\n"
4133 "for (int elem_count = 0; elem_count < single_value.n_elements; "
4135 "if (elem_count > 0) TTCN_Logger::log_event_str(\", \");\n"
4136 "single_value.value_elements[elem_count]->log_match"
4137 "(match_value[elem_count]);\n"
4139 "TTCN_Logger::log_event_str(\" }\");\n"
4140 "log_match_length(single_value.n_elements);\n"
4144 "match_value.log();\n"
4145 "TTCN_Logger::log_event_str(\" with \");\n"
4147 "if (match(match_value)) TTCN_Logger::log_event_str(\" matched\");\n");
4148 if (sdef
->kind
== SET_OF
) {
4149 src
= mputstr(src
, "else {\n"
4150 "TTCN_Logger::log_event_str(\" unmatched\");\n"
4151 "if (template_selection == SPECIFIC_VALUE) log_match_heuristics("
4152 "&match_value, match_value.size_of(), this, single_value.n_elements, "
4153 "match_function_specific, log_function);\n"
4156 src
= mputstr(src
, "else TTCN_Logger::log_event_str(\" unmatched\");\n"
4159 src
= mputstr(src
, "}\n\n");
4161 /* encoding/decoding functions */
4162 def
= mputstr(def
, "void encode_text(Text_Buf& text_buf) const;\n");
4163 src
= mputprintf(src
,
4164 "void %s_template::encode_text(Text_Buf& text_buf) const\n"
4166 "encode_text_%s(text_buf);\n"
4167 "switch (template_selection) {\n"
4168 "case SPECIFIC_VALUE:\n"
4169 "text_buf.push_int(single_value.n_elements);\n"
4170 "for (int elem_count = 0; elem_count < single_value.n_elements; "
4172 "single_value.value_elements[elem_count]->encode_text(text_buf);\n"
4173 "case OMIT_VALUE:\n"
4175 "case ANY_OR_OMIT:\n"
4177 "case VALUE_LIST:\n"
4178 "case COMPLEMENTED_LIST:\n"
4179 "text_buf.push_int(value_list.n_values);\n"
4180 "for (unsigned int list_count = 0; list_count < value_list.n_values; "
4182 "value_list.list_value[list_count].encode_text(text_buf);\n"
4183 "break;\n", name
, sdef
->kind
== RECORD_OF
? "permutation" : "restricted");
4184 if (sdef
->kind
== SET_OF
) {
4186 "case SUPERSET_MATCH:\n"
4187 "case SUBSET_MATCH:\n"
4188 "text_buf.push_int(value_set.n_items);\n"
4189 "for (unsigned int set_count = 0; set_count < value_set.n_items; "
4191 "value_set.set_items[set_count].encode_text(text_buf);\n"
4194 src
= mputprintf(src
,
4196 "TTCN_error(\"Text encoder: Encoding an uninitialized/unsupported "
4197 "template of type %s.\");\n"
4201 def
= mputstr(def
, "void decode_text(Text_Buf& text_buf);\n");
4202 src
= mputprintf(src
,
4203 "void %s_template::decode_text(Text_Buf& text_buf)\n"
4206 "decode_text_%s(text_buf);\n"
4207 "switch (template_selection) {\n"
4208 "case SPECIFIC_VALUE:\n"
4209 "single_value.n_elements = text_buf.pull_int().get_val();\n"
4210 "if (single_value.n_elements < 0) TTCN_error(\"Text decoder: Negative "
4211 "size was received for a template of type %s.\");\n"
4212 "single_value.value_elements = "
4213 "(%s_template**)allocate_pointers(single_value.n_elements);\n"
4214 "for (int elem_count = 0; elem_count < single_value.n_elements; "
4216 "single_value.value_elements[elem_count] = new %s_template;\n"
4217 "single_value.value_elements[elem_count]->decode_text(text_buf);\n"
4219 "case OMIT_VALUE:\n"
4221 "case ANY_OR_OMIT:\n"
4223 "case VALUE_LIST:\n"
4224 "case COMPLEMENTED_LIST:\n"
4225 "value_list.n_values = text_buf.pull_int().get_val();\n"
4226 "value_list.list_value = new %s_template[value_list.n_values];\n"
4227 "for (unsigned int list_count = 0; list_count < value_list.n_values; "
4229 "value_list.list_value[list_count].decode_text(text_buf);\n"
4230 "break;\n", name
, sdef
->kind
== RECORD_OF
? "permutation" : "restricted",
4231 dispname
, type
, type
, name
);
4232 if (sdef
->kind
== SET_OF
) {
4233 src
= mputprintf(src
,
4234 "case SUPERSET_MATCH:\n"
4235 "case SUBSET_MATCH:\n"
4236 "value_set.n_items = text_buf.pull_int().get_val();\n"
4237 "value_set.set_items = new %s_template[value_set.n_items];\n"
4238 "for (unsigned int set_count = 0; set_count < value_set.n_items; "
4240 "value_set.set_items[set_count].decode_text(text_buf);\n"
4243 src
= mputprintf(src
,
4245 "TTCN_error(\"Text decoder: An unknown/unsupported selection was "
4246 "received for a template of type %s.\");\n"
4250 /* TTCN-3 ispresent() function */
4251 def
= mputstr(def
, "boolean is_present() const;\n");
4252 src
= mputprintf(src
,
4253 "boolean %s_template::is_present() const\n"
4255 "if (template_selection==UNINITIALIZED_TEMPLATE) return FALSE;\n"
4256 "return !match_omit();\n"
4260 def
= mputstr(def
, "boolean match_omit() const;\n");
4261 src
= mputprintf(src
,
4262 "boolean %s_template::match_omit() const\n"
4264 "if (is_ifpresent) return TRUE;\n"
4265 "switch (template_selection) {\n"
4266 "case OMIT_VALUE:\n"
4267 "case ANY_OR_OMIT:\n"
4269 "case VALUE_LIST:\n"
4270 "case COMPLEMENTED_LIST:\n"
4271 "for (unsigned int i=0; i<value_list.n_values; i++)\n"
4272 "if (value_list.list_value[i].match_omit())\n"
4273 "return template_selection==VALUE_LIST;\n"
4274 "return template_selection==COMPLEMENTED_LIST;\n"
4282 def
= mputstr(def
, "void set_param(Module_Param& param);\n");
4283 src
= mputprintf(src
,
4284 "void %s_template::set_param(Module_Param& param)\n"
4286 " if (dynamic_cast<Module_Param_Name*>(param.get_id()) != NULL &&\n"
4287 " param.get_id()->next_name()) {\n"
4288 // Haven't reached the end of the module parameter name
4289 // => the name refers to one of the elements, not to the whole record of
4290 " char* param_field = param.get_id()->get_current_name();\n"
4291 " if (param_field[0] < '0' || param_field[0] > '9') {\n"
4292 " param.error(\"Unexpected record field name in module parameter, expected a valid\"\n"
4293 " \" index for %s template type `%s'\");\n"
4295 " int param_index = -1;\n"
4296 " sscanf(param_field, \"%%d\", ¶m_index);\n"
4297 " (*this)[param_index].set_param(param);\n"
4300 " param.basic_check(Module_Param::BC_TEMPLATE|Module_Param::BC_LIST, \"%s of template\");\n"
4301 " switch (param.get_type()) {\n"
4302 " case Module_Param::MP_Omit:\n"
4303 " *this = OMIT_VALUE;\n"
4305 " case Module_Param::MP_Any:\n"
4306 " *this = ANY_VALUE;\n"
4308 " case Module_Param::MP_AnyOrNone:\n"
4309 " *this = ANY_OR_OMIT;\n"
4311 " case Module_Param::MP_List_Template:\n"
4312 " case Module_Param::MP_ComplementList_Template:\n"
4313 " set_type(param.get_type()==Module_Param::MP_List_Template ? VALUE_LIST : COMPLEMENTED_LIST, param.get_size());\n"
4314 " for (size_t p_i=0; p_i<param.get_size(); p_i++) {\n"
4315 " list_item(p_i).set_param(*param.get_elem(p_i));\n"
4318 " case Module_Param::MP_Indexed_List:\n"
4319 " if (template_selection!=SPECIFIC_VALUE) set_size(0);\n"
4320 " for (size_t p_i=0; p_i<param.get_size(); ++p_i) {\n"
4321 " (*this)[(int)(param.get_elem(p_i)->get_id()->get_index())].set_param(*param.get_elem(p_i));\n"
4324 name
, sdef
->kind
==RECORD_OF
?"record":"set", dispname
, sdef
->kind
==RECORD_OF
?"record":"set");
4325 if (sdef
->kind
== RECORD_OF
) {
4327 " case Module_Param::MP_Value_List: {\n"
4328 " set_size(param.get_size());\n"
4329 " int curr_idx = 0;\n"
4330 " for (size_t p_i=0; p_i<param.get_size(); ++p_i) {\n"
4331 " switch (param.get_elem(p_i)->get_type()) {\n"
4332 " case Module_Param::MP_NotUsed:\n"
4335 " case Module_Param::MP_Permutation_Template: {\n"
4336 " int perm_start_idx = curr_idx;\n"
4337 " for (size_t perm_i=0; perm_i<param.get_elem(p_i)->get_size(); perm_i++) {\n"
4338 " (*this)[curr_idx].set_param(*(param.get_elem(p_i)->get_elem(perm_i)));\n"
4341 " int perm_end_idx = curr_idx - 1;\n"
4342 " add_permutation(perm_start_idx, perm_end_idx);\n"
4345 " (*this)[curr_idx].set_param(*param.get_elem(p_i));\n"
4352 " case Module_Param::MP_Value_List:\n"
4353 " set_size(param.get_size());\n"
4354 " for (size_t p_i=0; p_i<param.get_size(); ++p_i) {\n"
4355 " if (param.get_elem(p_i)->get_type()!=Module_Param::MP_NotUsed) {\n"
4356 " (*this)[p_i].set_param(*param.get_elem(p_i));\n"
4360 " case Module_Param::MP_Superset_Template:\n"
4361 " case Module_Param::MP_Subset_Template:\n"
4362 " set_type(param.get_type()==Module_Param::MP_Superset_Template ? SUPERSET_MATCH : SUBSET_MATCH, param.get_size());\n"
4363 " for (size_t p_i=0; p_i<param.get_size(); p_i++) {\n"
4364 " set_item(p_i).set_param(*param.get_elem(p_i));\n"
4368 src
= mputprintf(src
,
4370 " param.type_error(\"%s of template\", \"%s\");\n"
4372 " is_ifpresent = param.get_ifpresent();\n"
4373 " set_length_range(param);\n"
4374 "}\n\n", sdef
->kind
==RECORD_OF
?"record":"set", dispname
);
4376 /* check template restriction */
4377 def
= mputstr(def
, "void check_restriction(template_res t_res, "
4378 "const char* t_name=NULL) const;\n");
4379 src
= mputprintf(src
,
4380 "void %s_template::check_restriction("
4381 "template_res t_res, const char* t_name) const\n"
4383 "if (template_selection==UNINITIALIZED_TEMPLATE) return;\n"
4384 "switch ((t_name&&(t_res==TR_VALUE))?TR_OMIT:t_res) {\n"
4386 "if (template_selection==OMIT_VALUE) return;\n"
4388 "if (template_selection!=SPECIFIC_VALUE || is_ifpresent) break;\n"
4389 "for (int i=0; i<single_value.n_elements; i++) "
4390 "single_value.value_elements[i]->check_restriction("
4391 "t_res, t_name ? t_name : \"%s\");\n"
4393 "case TR_PRESENT:\n"
4394 "if (!match_omit()) return;\n"
4399 "TTCN_error(\"Restriction `%%s' on template of type %%s "
4400 "violated.\", get_res_name(t_res), t_name ? t_name : \"%s\");\n"
4401 "}\n\n", name
, dispname
, dispname
);
4404 def
= mputstr(def
, "};\n\n");
4406 output
->header
.class_decls
= mputprintf(output
->header
.class_decls
,
4407 "class %s_template;\n", name
);
4408 output
->header
.class_defs
= mputstr(output
->header
.class_defs
, def
);
4410 output
->source
.methods
= mputstr(output
->source
.methods
, src
);
4414 /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
4416 void defRecordOfTemplate2(const struct_of_def
*sdef
, output_struct
*output
)
4418 char *def
= NULL
, *src
= NULL
;
4419 const char *name
= sdef
->name
;
4420 const char *type
= sdef
->type
;
4421 const char *base_class
= sdef
->kind
== RECORD_OF
? "Record_Of_Template" : "Set_Of_Template";
4423 /* Class definition */
4424 def
= mputprintf(def
, "class %s_template : public %s {\n", name
, base_class
);
4426 /* public member functions */
4427 def
= mputstr(def
, "\npublic:\n");
4430 def
= mputprintf(def
, "%s_template() {}\n", name
);
4432 def
= mputprintf(def
, "%s_template(template_sel other_value): %s(other_value) "
4433 "{ check_single_selection(other_value); }\n", name
, base_class
);
4435 def
= mputprintf(def
, "%s_template(null_type other_value);\n", name
);
4436 src
= mputprintf(src
, "%s_template::%s_template(null_type)\n"
4437 " : %s(SPECIFIC_VALUE)\n"
4439 "single_value.n_elements = 0;\n"
4440 "single_value.value_elements = NULL;\n"
4441 "}\n\n", name
, name
, base_class
);
4443 def
= mputprintf(def
, "%s_template(const %s& other_value) "
4444 "{ copy_value(&other_value); }\n", name
, name
);
4445 def
= mputprintf(def
, "%s_template(const OPTIONAL<%s>& other_value) "
4446 "{ copy_optional(&other_value); }\n", name
, name
);
4448 /* copy constructor */
4449 def
= mputprintf(def
, "%s_template(const %s_template& other_value): %s() { copy_template(other_value); }\n",
4450 name
, name
, base_class
);
4452 /* assignment operators */
4453 def
= mputprintf(def
, "%s_template& operator=(template_sel other_value);\n",
4455 src
= mputprintf(src
,
4456 "%s_template& %s_template::operator=(template_sel other_value)\n"
4458 "check_single_selection(other_value);\n"
4460 "set_selection(other_value);\n"
4462 "}\n\n", name
, name
);
4464 def
= mputprintf(def
, "%s_template& operator=(null_type other_value);\n",
4466 src
= mputprintf(src
,
4467 "%s_template& %s_template::operator=(null_type)\n"
4470 "set_selection(SPECIFIC_VALUE);\n"
4471 "single_value.n_elements = 0;\n"
4472 "single_value.value_elements = NULL;\n"
4474 "}\n\n", name
, name
);
4476 def
= mputprintf(def
, "%s_template& operator=(const %s& other_value);\n",
4478 src
= mputprintf(src
,
4479 "%s_template& %s_template::operator=(const %s& other_value)\n"
4482 "copy_value(&other_value);\n"
4484 "}\n\n", name
, name
, name
);
4486 def
= mputprintf(def
, "%s_template& operator=(const OPTIONAL<%s>& "
4487 "other_value);\n", name
, name
);
4488 src
= mputprintf(src
,
4489 "%s_template& %s_template::operator=(const OPTIONAL<%s>& other_value)\n"
4492 "copy_optional(&other_value);\n"
4494 "}\n\n", name
, name
, name
);
4496 def
= mputprintf(def
, "%s_template& operator=(const %s_template& "
4497 "other_value);\n\n", name
, name
);
4498 src
= mputprintf(src
,
4499 "%s_template& %s_template::operator=(const %s_template& other_value)\n"
4501 "if (&other_value != this) {\n"
4503 "copy_template(other_value);\n"
4506 "}\n\n", name
, name
, name
);
4508 /* indexing operators */
4509 def
= mputprintf(def
,
4510 "%s_template& operator[](int index_value);\n"
4511 "%s_template& operator[](const INTEGER& index_value);\n"
4512 "const %s_template& operator[](int index_value) const;\n"
4513 "const %s_template& operator[](const INTEGER& index_value) const;\n",
4519 src
= mputprintf(src
,
4520 "%s_template& %s_template::operator[](int index_value) { return *(static_cast<%s_template*>(get_at(index_value))); }\n"
4521 "%s_template& %s_template::operator[](const INTEGER& index_value) { return *(static_cast<%s_template*>(get_at(index_value))); }\n"
4522 "const %s_template& %s_template::operator[](int index_value) const { return *(static_cast<const %s_template*>(get_at(index_value))); }\n"
4523 "const %s_template& %s_template::operator[](const INTEGER& index_value) const { return *(static_cast<const %s_template*>(get_at(index_value))); }\n\n",
4529 /* match operation */
4530 def
= mputprintf(def
, "inline boolean match(const %s& match_value) const "
4531 "{ return matchv(&match_value); }\n", name
);
4533 /* valueof operation */
4534 def
= mputprintf(def
, "%s valueof() const;\n", name
);
4535 src
= mputprintf(src
,
4536 "%s %s_template::valueof() const\n"
4539 "valueofv(&ret_val);\n"
4541 "}\n\n", name
, name
, name
);
4543 /* substr() predefined function for templates */
4544 def
= mputprintf(def
,
4545 "%s substr(int index, int returncount) const;\n\n", name
);
4546 src
= mputprintf(src
,
4547 "%s %s_template::substr(int index, int returncount) const\n"
4550 "substr_(index, returncount, &rec_of);\n"
4552 "}\n\n", name
, name
, name
);
4554 /* replace() predefined function for templates */
4555 def
= mputprintf(def
,
4556 "%s replace(int index, int len, const %s_template& repl) const;\n\n",
4558 src
= mputprintf(src
,
4559 "%s %s_template::replace(int index, int len, const %s_template& repl) const\n"
4562 "replace_(index, len, &repl, &rec_of);\n"
4564 "}\n\n", name
, name
, name
, name
);
4565 def
= mputprintf(def
,
4566 "%s replace(int index, int len, const %s& repl) const;\n\n",
4568 src
= mputprintf(src
,
4569 "%s %s_template::replace(int index, int len, const %s& repl) const\n"
4572 "replace_(index, len, &repl, &rec_of);\n"
4574 "}\n\n", name
, name
, name
, name
);
4576 /* value list and set handling operators */
4577 def
= mputprintf(def
,
4578 "inline %s_template& list_item(int list_index) { return *(static_cast<%s_template*>(get_list_item(list_index))); }\n", name
, name
);
4580 if (sdef
->kind
== SET_OF
) {
4581 def
= mputprintf(def
, "%s_template& set_item(int set_index);\n", type
);
4582 src
= mputprintf(src
,
4583 "%s_template& %s_template::set_item(int set_index) "
4584 "{ return *(static_cast<%s_template*>(get_set_item(set_index))); }\n",
4588 /* logging functions */
4589 def
= mputprintf(def
, "inline void log_match(const %s& match_value) const "
4590 "{ log_matchv(&match_value); }\n", name
);
4592 /* virtual helper functions */
4593 def
= mputprintf(def
,
4594 "%s* create() const { return new %s_template; }\n"
4595 "Base_Template* create_elem() const;\n"
4596 "const TTCN_Typedescriptor_t* get_descriptor() const;\n",
4598 src
= mputprintf(src
,
4599 "Base_Template* %s_template::create_elem() const { return new %s_template; }\n"
4600 "const TTCN_Typedescriptor_t* %s_template::get_descriptor() const { return &%s_descr_; }\n",
4605 def
= mputstr(def
, "};\n\n");
4607 output
->header
.class_decls
= mputprintf(output
->header
.class_decls
,
4608 "class %s_template;\n", name
);
4609 output
->header
.class_defs
= mputstr(output
->header
.class_defs
, def
);
4611 output
->source
.methods
= mputstr(output
->source
.methods
, src
);
This page took 0.272383 seconds and 5 git commands to generate.