Newer
Older
/******************************************************************************
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.html
*
* Contributors:
* Baji, Laszlo
* Balasko, Jeno
* Baranyi, Botond
* Beres, Szabolcs
* Delic, Adam
* Forstner, Matyas
* Kovacs, Ferenc
* Raduly, Csaba
* Szabados, Kristof
* Szabo, Bence Janos
* Szabo, Janos Zoltan – initial implementation
* Szalai, Gabor
* Zalanyi, Balazs Andor
*
******************************************************************************/
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
#include "../common/memory.h"
#include "datatypes.h"
#include "record_of.h"
#include "encdec.h"
#include "main.hh"
#include "ttcn3/compiler.h"
/** code generation for original runtime */
static void defRecordOfClass1(const struct_of_def *sdef, output_struct *output);
static void defRecordOfTemplate1(const struct_of_def *sdef, output_struct *output);
/** code generation for alternative runtime (TITAN_RUNTIME_2) */
static void defRecordOfClass2(const struct_of_def *sdef, output_struct *output);
static void defRecordOfTemplate2(const struct_of_def *sdef, output_struct *output);
void defRecordOfClass(const struct_of_def *sdef, output_struct *output)
{
if (use_runtime_2) defRecordOfClass2(sdef, output);
else defRecordOfClass1(sdef, output);
}
void defRecordOfTemplate(const struct_of_def *sdef, output_struct *output)
{
if (use_runtime_2) defRecordOfTemplate2(sdef, output);
else defRecordOfTemplate1(sdef, output);
}
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
void defRecordOfClass1(const struct_of_def *sdef, output_struct *output)
{
char *def = NULL, *src = NULL;
const char *name = sdef->name, *dispname = sdef->dispname;
const char *type = sdef->type;
boolean ber_needed = force_gen_seof || (sdef->isASN1 && enable_ber());
boolean raw_needed = force_gen_seof || (sdef->hasRaw && enable_raw());
boolean text_needed = force_gen_seof || (sdef->hasText && enable_text());
boolean xer_needed = force_gen_seof || (sdef->hasXer && enable_xer());
boolean json_needed = force_gen_seof || (sdef->hasJson && enable_json());
boolean oer_needed = force_gen_seof || (sdef->hasOer && enable_oer());
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
/* Class definition and private data members */
def = mputprintf(def,
#ifndef NDEBUG
"// written by %s in " __FILE__ " at %d\n"
#endif
"class %s : public Base_Type {\n"
"struct recordof_setof_struct {\n"
"int ref_count;\n"
"int n_elements;\n"
"%s **value_elements;\n"
"} *val_ptr;\n"
#ifndef NDEBUG
, __FUNCTION__, __LINE__
#endif
, name, type);
/* constant unbound element */
def = mputprintf(def, "\nstatic const %s UNBOUND_ELEM;\n", type);
src = mputprintf(src, "\nconst %s %s::UNBOUND_ELEM;\n", type, name);
/* private member functions */
def = mputprintf(def,
"private:\n"
"friend boolean operator==(null_type null_value, "
"const %s& other_value);\n", name);
if (sdef->kind == SET_OF) {
/* callback function for comparison */
def = mputstr(def, "static boolean compare_function("
"const Base_Type *left_ptr, int left_index, "
"const Base_Type *right_ptr, int right_index);\n");
src = mputprintf(src, "boolean %s::compare_function("
"const Base_Type *left_ptr, int left_index, "
"const Base_Type *right_ptr, int right_index)\n"
"{\n"
"if (((const %s*)left_ptr)->val_ptr == NULL) "
"TTCN_error(\"The left operand of comparison is an unbound value of "
"type %s.\");\n"
"if (((const %s*)right_ptr)->val_ptr == NULL) "
"TTCN_error(\"The right operand of comparison is an unbound value of "
"type %s.\");\n"
"if (((const %s*)left_ptr)->val_ptr->value_elements[left_index] != NULL){\n"
"if (((const %s*)right_ptr)->val_ptr->value_elements[right_index] != NULL){\n"
"return *((const %s*)left_ptr)->val_ptr->value_elements[left_index] == "
"*((const %s*)right_ptr)->val_ptr->value_elements[right_index];\n"
"} else return FALSE;\n"
"} else {\n"
"return ((const %s*)right_ptr)->val_ptr->value_elements[right_index] == NULL;\n"
"}\n"
"}\n\n", name, name, dispname, name, dispname, name, name, name, name, name);
}
/* public member functions */
def = mputstr(def, "\npublic:\n");
def = mputprintf(def, " typedef %s of_type;\n", sdef->type);
/* constructors */
def = mputprintf(def, "%s();\n", name);
src = mputprintf(src,
"%s::%s()\n"
"{\n"
"val_ptr = NULL;\n"
"}\n\n", name, name);
def = mputprintf(def, "%s(null_type other_value);\n", name);
src = mputprintf(src,
"%s::%s(null_type)\n"
"{\n"
"val_ptr = new recordof_setof_struct;\n"
"val_ptr->ref_count = 1;\n"
"val_ptr->n_elements = 0;\n"
"val_ptr->value_elements = NULL;\n"
"}\n\n", name, name);
/* copy constructor */
def = mputprintf(def, "%s(const %s& other_value);\n", name, name);
src = mputprintf(src,
"%s::%s(const %s& other_value)\n"
"{\n"
"if (!other_value.is_bound()) "
"TTCN_error(\"Copying an unbound value of type %s.\");\n"
"val_ptr = other_value.val_ptr;\n"
"val_ptr->ref_count++;\n"
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
/* destructor */
def = mputprintf(def, "~%s();\n\n", name);
src = mputprintf(src,
"%s::~%s()\n"
"{\n"
"clean_up();\n"
"if (val_ptr != NULL) val_ptr = NULL;\n"
"}\n\n", name, name);
/* clean_up function */
def = mputstr(def, "void clean_up();\n");
src = mputprintf
(src,
"void %s::clean_up()\n"
"{\n"
"if (val_ptr != NULL) {\n"
"if (val_ptr->ref_count > 1) {\n"
"val_ptr->ref_count--;\n"
"val_ptr = NULL;\n"
"}\n"
"else if (val_ptr->ref_count == 1) {\n"
"for (int elem_count = 0; elem_count < val_ptr->n_elements;\n"
"elem_count++)\n"
"if (val_ptr->value_elements[elem_count] != NULL)\n"
"delete val_ptr->value_elements[elem_count];\n"
"free_pointers((void**)val_ptr->value_elements);\n"
"delete val_ptr;\n"
"val_ptr = NULL;\n"
"}\n"
"else\n"
"TTCN_error(\"Internal error: Invalid reference counter in a record "
"of/set of value.\");\n"
"}\n"
"}\n\n", name);
/* assignment operators */
def = mputprintf(def, "%s& operator=(null_type other_value);\n", name);
src = mputprintf(src,
"%s& %s::operator=(null_type)\n"
"{\n"
"clean_up();\n"
"val_ptr = new recordof_setof_struct;\n"
"val_ptr->ref_count = 1;\n"
"val_ptr->n_elements = 0;\n"
"val_ptr->value_elements = NULL;\n"
"return *this;\n"
"}\n\n", name, name);
def = mputprintf(def, "%s& operator=(const %s& other_value);\n\n",
name, name);
src = mputprintf(src,
"%s& %s::operator=(const %s& other_value)\n"
"{\n"
"TTCN_error(\"Assigning an unbound value of type %s.\");\n"
"if (this != &other_value) {\n"
"clean_up();\n"
"val_ptr = other_value.val_ptr;\n"
"val_ptr->ref_count++;\n"
"}\n"
"return *this;\n"
/* comparison operators */
def = mputstr(def, "boolean operator==(null_type other_value) const;\n");
src = mputprintf(src,
"boolean %s::operator==(null_type) const\n"
"{\n"
"if (val_ptr == NULL)\n"
"TTCN_error(\"The left operand of comparison is an unbound value of "
"type %s.\");\n"
"}\n\n", name, dispname);
def = mputprintf(def, "boolean operator==(const %s& other_value) const;\n",
name);
src = mputprintf(src,
"boolean %s::operator==(const %s& other_value) const\n"
"{\n"
"if (val_ptr == NULL) "
"TTCN_error(\"The left operand of comparison is an unbound value of type "
"%s.\");\n"
"if (other_value.val_ptr == NULL) "
"TTCN_error(\"The right operand of comparison is an unbound value of type "
"%s.\");\n"
"if (val_ptr == other_value.val_ptr) return TRUE;\n", name, name,
dispname, dispname);
if (sdef->kind == SET_OF) {
src = mputstr(src,
"return compare_set_of(this, val_ptr->n_elements, &other_value, "
"(other_value.val_ptr)->n_elements, compare_function);\n");
"if (val_ptr->n_elements != (other_value.val_ptr)->n_elements)\n"
"for (int elem_count = 0; elem_count < val_ptr->n_elements; elem_count++){\n"
"if (val_ptr->value_elements[elem_count] != NULL){\n"
"if ((other_value.val_ptr)->value_elements[elem_count] != NULL){\n"
" if (*val_ptr->value_elements[elem_count] != "
"*(other_value.val_ptr)->value_elements[elem_count]) "
"return FALSE;\n"
"} else return FALSE;\n"
"} else {\n"
"if ((other_value.val_ptr)->value_elements[elem_count] != NULL) "
"return FALSE;\n"
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
"}\n"
"}\n"
"return TRUE;\n");
}
src = mputstr(src, "}\n\n");
def = mputstr(def, "inline boolean operator!=(null_type other_value) const "
"{ return !(*this == other_value); }\n");
def = mputprintf(def, "inline boolean operator!=(const %s& other_value) "
"const { return !(*this == other_value); }\n\n", name);
/* indexing operators */
/* Non-const operator[] is allowed to extend the record-of */
def = mputprintf(def, "%s& operator[](int index_value);\n", type);
src = mputprintf(src,
"%s& %s::operator[](int index_value)\n"
"{\n"
"if (index_value < 0) TTCN_error(\"Accessing an element of type %s "
"using a negative index: %%d.\", index_value);\n"
"if (val_ptr == NULL) {\n"
"val_ptr = new recordof_setof_struct;\n"
"val_ptr->ref_count = 1;\n"
"val_ptr->n_elements = 0;\n"
"val_ptr->value_elements = NULL;\n"
"} else if (val_ptr->ref_count > 1) {\n" /* copy-on-write */
"struct recordof_setof_struct *new_val_ptr = new recordof_setof_struct;\n"
"new_val_ptr->ref_count = 1;\n"
"new_val_ptr->n_elements = (index_value >= val_ptr->n_elements) ? "
"index_value + 1 : val_ptr->n_elements;\n"
"new_val_ptr->value_elements = "
"(%s**)allocate_pointers(new_val_ptr->n_elements);\n"
"for (int elem_count = 0; elem_count < val_ptr->n_elements; "
"elem_count++){\n"
"if (val_ptr->value_elements[elem_count] != NULL){\n"
"new_val_ptr->value_elements[elem_count] = "
"new %s(*(val_ptr->value_elements[elem_count]));\n"
"}\n"
"}\n"
"clean_up();\n"
"val_ptr = new_val_ptr;\n"
"}\n"
"if (index_value >= val_ptr->n_elements) set_size(index_value + 1);\n"
"if (val_ptr->value_elements[index_value] == NULL) {\n"
"val_ptr->value_elements[index_value] = new %s;\n"
"}\n"
"return *val_ptr->value_elements[index_value];\n"
"}\n\n", type, name, dispname, type, type, type);
def = mputprintf(def, "%s& operator[](const INTEGER& index_value);\n",
type);
src = mputprintf(src,
"%s& %s::operator[](const INTEGER& index_value)\n"
"{\n"
"index_value.must_bound(\"Using an unbound integer value for indexing "
"a value of type %s.\");\n"
"return (*this)[(int)index_value];\n"
"}\n\n", type, name, dispname);
/* Const operator[] throws an error if over-indexing */
def = mputprintf(def, "const %s& operator[](int index_value) const;\n",
type);
src = mputprintf(src,
"const %s& %s::operator[](int index_value) const\n"
"{\n"
"if (val_ptr == NULL)\n"
"TTCN_error(\"Accessing an element in an unbound value of type %s.\");\n"
"if (index_value < 0) TTCN_error(\"Accessing an element of type %s "
"using a negative index: %%d.\", index_value);\n"
"if (index_value >= val_ptr->n_elements) TTCN_error(\"Index overflow in "
"a value of type %s: The index is %%d, but the value has only %%d "
"return (val_ptr->value_elements[index_value] == NULL) ?\n"
"UNBOUND_ELEM : *val_ptr->value_elements[index_value];\n"
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
"}\n\n", type, name, dispname, dispname, dispname);
def = mputprintf(def, "const %s& operator[](const INTEGER& index_value) "
"const;\n\n", type);
src = mputprintf(src,
"const %s& %s::operator[](const INTEGER& index_value) const\n"
"{\n"
"index_value.must_bound(\"Using an unbound integer value for indexing "
"a value of type %s.\");\n"
"return (*this)[(int)index_value];\n"
"}\n\n", type, name, dispname);
/* rotation operators */
def = mputprintf(def,
"%s operator<<=(int rotate_count) const;\n"
"%s operator<<=(const INTEGER& rotate_count) const;\n"
"%s operator>>=(int rotate_count) const;\n"
"%s operator>>=(const INTEGER& rotate_count) const;\n\n",
name, name, name, name);
src = mputprintf(src,
"%s %s::operator<<=(int rotate_count) const\n"
"{\n"
"return *this >>= (-rotate_count);\n"
"}\n\n"
"%s %s::operator<<=(const INTEGER& rotate_count) const\n"
"{\n"
"rotate_count.must_bound(\""
"Unbound integer operand of rotate left operator.\");\n"
"return *this >>= (int)(-rotate_count);\n"
"}\n\n"
"%s %s::operator>>=(const INTEGER& rotate_count) const\n"
"{\n"
"rotate_count.must_bound(\""
"Unbound integer operand of rotate right operator.\");\n"
"return *this >>= (int)rotate_count;\n"
"}\n\n"
"%s %s::operator>>=(int rotate_count) const\n"
"{\n"
"if (val_ptr == NULL) "
"TTCN_error(\"Performing rotation operation on an unbound value of type "
"%s.\");\n"
"if (rotate_count>=0) rc = rotate_count %% val_ptr->n_elements;\n"
"else rc = val_ptr->n_elements - ((-rotate_count) %% val_ptr->n_elements);\n"
"if (rc == 0) return *this;\n"
"%s ret_val;\n"
"ret_val.set_size(val_ptr->n_elements);\n"
"for (int i=0; i<val_ptr->n_elements; i++) {\n"
"if (val_ptr->value_elements[i] != NULL) {\n"
"ret_val.val_ptr->value_elements[(i+rc)%%val_ptr->n_elements] ="
"new %s(*val_ptr->value_elements[i]);\n"
"}\n"
"}\n"
"return ret_val;\n"
"}\n\n",
name, name, name, name, name, name, name, name, dispname, name, type);
/* concatenation */
def = mputprintf(def,
"%s operator+(const %s& other_value) const;\n\n", name, name);
src = mputprintf(src,
"%s %s::operator+(const %s& other_value) const\n"
"{\n"
"if (val_ptr == NULL || other_value.val_ptr == NULL) "
"TTCN_error(\"Unbound operand of %s concatenation.\");\n"
"if (val_ptr->n_elements == 0) return other_value;\n"
"if (other_value.val_ptr->n_elements == 0) return *this;\n"
"ret_val.set_size(val_ptr->n_elements+other_value.val_ptr->n_elements);\n"
"for (int i=0; i<val_ptr->n_elements; i++) {\n"
"if (val_ptr->value_elements[i] != NULL) {\n"
"ret_val.val_ptr->value_elements[i] = new %s(*val_ptr->value_elements[i]);\n"
"}\n"
"}\n"
"for (int i=0; i<other_value.val_ptr->n_elements; i++) {\n"
"if (other_value.val_ptr->value_elements[i] != NULL) {\n"
"ret_val.val_ptr->value_elements[i+val_ptr->n_elements] = "
"new %s(*other_value.val_ptr->value_elements[i]);\n"
"}\n"
"}\n"
"return ret_val;\n"
"}\n\n", name, name, name, dispname, name, type, type);
/* substr() */
def = mputprintf(def,
"%s substr(int index, int returncount) const;\n\n", name);
src = mputprintf(src,
"%s %s::substr(int index, int returncount) const\n"
"{\n"
"if (val_ptr == NULL) "
"TTCN_error(\"The first argument of substr() is an unbound value of "
"type %s.\");\n"
"check_substr_arguments(val_ptr->n_elements, index, returncount, "
"\"%s\",\"element\");\n"
"%s ret_val;\n"
"ret_val.set_size(returncount);\n"
"for (int i=0; i<returncount; i++) {\n"
"ret_val.val_ptr->value_elements[i] = "
"new %s(*val_ptr->value_elements[i+index]);\n"
"}\n"
"}\n"
"return ret_val;\n"
"}\n\n", name, name, dispname, dispname, name, type);
/* replace() */
def = mputprintf(def,
"%s replace(int index, int len, const %s& repl) const;\n\n", name, name);
src = mputprintf(src,
"%s %s::replace(int index, int len, const %s& repl) const\n"
"{\n"
"if (val_ptr == NULL) "
"TTCN_error(\"The first argument of replace() is an unbound value of "
"type %s.\");\n"
"if (repl.val_ptr == NULL) "
"TTCN_error(\"The fourth argument of replace() is an unbound value of "
"type %s.\");\n"
"check_replace_arguments(val_ptr->n_elements, index, len, "
"\"%s\",\"element\");\n"
"%s ret_val;\n"
"ret_val.set_size(val_ptr->n_elements + repl.val_ptr->n_elements - len);\n"
"ret_val.val_ptr->value_elements[i] = new %s(*val_ptr->value_elements[i]);\n"
"}\n"
"}\n"
"for (int i = 0; i < repl.val_ptr->n_elements; i++) {\n"
"if (repl.val_ptr->value_elements[i] != NULL) {\n"
"ret_val.val_ptr->value_elements[i+index] = "
"new %s(*repl.val_ptr->value_elements[i]);\n"
"}\n"
"}\n"
"for (int i = 0; i < val_ptr->n_elements - index - len; i++) {\n"
"if (val_ptr->value_elements[index+i+len] != NULL) {\n"
"ret_val.val_ptr->value_elements[index+i+repl.val_ptr->n_elements] = "
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
"new %s(*val_ptr->value_elements[index+i+len]);\n"
"}\n"
"}\n"
"return ret_val;\n"
"}\n\n", name, name, name, dispname, dispname, dispname, name, type, type, type);
def = mputprintf(def,
"%s replace(int index, int len, const %s_template& repl) const;\n\n",
name, name);
src = mputprintf(src,
"%s %s::replace(int index, int len, const %s_template& repl) const\n"
"{\n"
"if (!repl.is_value()) TTCN_error(\"The fourth argument of function "
"replace() is a template with non-specific value.\");\n"
"return replace(index, len, repl.valueof());\n"
"}\n\n", name, name, name);
/* set_size function */
def = mputstr(def, "void set_size(int new_size);\n");
src = mputprintf(src, "void %s::set_size(int new_size)\n"
"{\n"
"if (new_size < 0) TTCN_error(\"Internal error: Setting a negative size "
"for a value of type %s.\");\n"
"if (val_ptr == NULL) {\n"
"val_ptr = new recordof_setof_struct;\n"
"val_ptr->ref_count = 1;\n"
"val_ptr->n_elements = 0;\n"
"val_ptr->value_elements = NULL;\n"
"} else if (val_ptr->ref_count > 1) {\n" /* copy-on-write */
"struct recordof_setof_struct *new_val_ptr = new recordof_setof_struct;\n"
"new_val_ptr->ref_count = 1;\n"
"new_val_ptr->n_elements = (new_size < val_ptr->n_elements) ? "
"new_size : val_ptr->n_elements;\n"
"new_val_ptr->value_elements = "
"(%s**)allocate_pointers(new_val_ptr->n_elements);\n"
"for (int elem_count = 0; elem_count < new_val_ptr->n_elements; "
"elem_count++) {\n"
"if (val_ptr->value_elements[elem_count] != NULL){\n"
"new_val_ptr->value_elements[elem_count] = "
"new %s(*(val_ptr->value_elements[elem_count]));\n"
"}\n"
"}\n"
"clean_up();\n"
"val_ptr = new_val_ptr;\n"
"}\n"
"if (new_size > val_ptr->n_elements) {\n"
"val_ptr->value_elements = (%s**)"
"reallocate_pointers((void**)val_ptr->value_elements, "
"val_ptr->n_elements, new_size);\n"
"#ifdef TITAN_MEMORY_DEBUG_SET_RECORD_OF\n"
"if((val_ptr->n_elements/1000)!=(new_size/1000)) "
"TTCN_warning(\"New size of type %s: %%d\",new_size);\n"
"#endif\n"
"val_ptr->n_elements = new_size;\n"
"} else if (new_size < val_ptr->n_elements) {\n"
"for (int elem_count = new_size; elem_count < val_ptr->n_elements; "
"elem_count++)\n"
"if (val_ptr->value_elements[elem_count] != NULL)"
"delete val_ptr->value_elements[elem_count];\n"
"val_ptr->value_elements = (%s**)"
"reallocate_pointers((void**)val_ptr->value_elements, "
"val_ptr->n_elements, new_size);\n"
"val_ptr->n_elements = new_size;\n"
"}\n"
"}\n\n", name, dispname, type, type, type, dispname, type);
/* is_bound function */
def = mputstr(def,
"inline boolean is_bound() const {return val_ptr != NULL; }\n");
/* is_present function */
def = mputstr(def,
"inline boolean is_present() const { return is_bound(); }\n");
/* is_value function */
def = mputstr(def,
"boolean is_value() const;\n");
src = mputprintf(src,
"boolean %s::is_value() const\n"
"{\n"
"if (val_ptr == NULL) return FALSE;\n"
"for(int i = 0; i < val_ptr->n_elements; ++i) {\n"
"if (val_ptr->value_elements[i] == NULL || "
"!val_ptr->value_elements[i]->is_value()) return FALSE;\n"
"}\n"
"return TRUE;\n"
"}\n\n", name);
/* sizeof operation */
def = mputstr(def,
"int size_of() const;\n"
"int n_elem() const { return size_of(); }\n");
src = mputprintf(src,
"int %s::size_of() const\n"
"{\n"
"if (val_ptr == NULL) "
"TTCN_error(\"Performing sizeof operation on an unbound value of type "
"%s.\");\n"
"}\n\n", name, dispname);
/* lengthof operation */
def = mputstr(def, "int lengthof() const;\n");
src = mputprintf(src,
"int %s::lengthof() const\n"
"{\n"
"if (val_ptr == NULL) "
"TTCN_error(\"Performing lengthof operation on an unbound value of type "
"%s.\");\n"
"for (int my_length=val_ptr->n_elements; my_length>0; my_length--) "
"if (val_ptr->value_elements[my_length-1] != NULL) return my_length;\n"
"return 0;\n"
"}\n\n", name, dispname);
/* log function */
def = mputstr(def, "void log() const;\n");
src = mputprintf
(src,
"void %s::log() const\n"
"{\n"
"if (val_ptr == NULL) {;\n"
"TTCN_Logger::log_event_unbound();\n"
"return;\n"
"}\n"
"case 0:\n"
"TTCN_Logger::log_event_str(\"{ }\");\n"
"break;\n"
"default:\n"
"TTCN_Logger::log_event_str(\"{ \");\n"
"for (int elem_count = 0; elem_count < val_ptr->n_elements; "
"elem_count++) {\n"
"if (elem_count > 0) TTCN_Logger::log_event_str(\", \");\n"
"(*this)[elem_count].log();\n"
"}\n"
"TTCN_Logger::log_event_str(\" }\");\n"
"}\n"
"}\n\n", name);
/* set_param function */
def = mputstr(def, "void set_param(Module_Param& param);\n");
src = mputprintf(src,
"void %s::set_param(Module_Param& param)\n"
"{\n"
" param.basic_check(Module_Param::BC_VALUE|Module_Param::BC_LIST, \"%s value\");\n"
" switch (param.get_operation_type()) {\n"
" case Module_Param::OT_ASSIGN:\n"
" if (param.get_type()==Module_Param::MP_Value_List && param.get_size()==0) {\n"
" *this = NULL_VALUE;\n"
" return;\n"
" }\n"
" switch (param.get_type()) {\n"
" set_size(param.get_size());\n"
" for (size_t i=0; i<param.get_size(); ++i) {\n"
" Module_Param* const curr = param.get_elem(i);\n"
" if (curr->get_type()!=Module_Param::MP_NotUsed) {\n"
" (*this)[i].set_param(*curr);\n"
Botond Baranyi
committed
" if (!(*this)[i].is_bound()) {\n"
" delete val_ptr->value_elements[i];\n"
" val_ptr->value_elements[i] = NULL;\n"
" }\n"
" }\n"
" }\n"
" break;\n"
" case Module_Param::MP_Indexed_List:\n"
" for (size_t i=0; i<param.get_size(); ++i) {\n"
" Module_Param* const curr = param.get_elem(i);\n"
" (*this)[curr->get_id()->get_index()].set_param(*curr);\n"
Botond Baranyi
committed
" if (!(*this)[curr->get_id()->get_index()].is_bound()) {\n"
" delete val_ptr->value_elements[curr->get_id()->get_index()];\n"
" val_ptr->value_elements[curr->get_id()->get_index()] = NULL;\n"
" }\n"
" }\n"
" break;\n"
" default:\n"
" param.type_error(\"%s value\", \"%s\");\n"
" }\n"
" break;\n"
" case Module_Param::OT_CONCAT:\n"
" switch (param.get_type()) {\n"
" case Module_Param::MP_Value_List: {\n"
" if (!is_bound()) *this = NULL_VALUE;\n"
" int start_idx = lengthof();\n"
" for (size_t i=0; i<param.get_size(); ++i) {\n"
" Module_Param* const curr = param.get_elem(i);\n"
" if ((curr->get_type()!=Module_Param::MP_NotUsed)) {\n"
" (*this)[start_idx+(int)i].set_param(*curr);\n"
" }\n"
" }\n"
" } break;\n"
" case Module_Param::MP_Indexed_List:\n"
" param.error(\"Cannot concatenate an indexed value list\");\n"
" break;\n"
" default:\n"
" param.type_error(\"%s value\", \"%s\");\n"
" }\n"
" break;\n"
" default:\n"
" TTCN_error(\"Internal error: Unknown operation type.\");\n"
" }\n"
"}\n\n", name, sdef->kind == RECORD_OF ? "record of" : "set of",
sdef->kind == RECORD_OF ? "record of" : "set of", dispname,
sdef->kind == RECORD_OF ? "record of" : "set of", dispname);
/* set implicit omit function, recursive */
def = mputstr(def, " void set_implicit_omit();\n");
src = mputprintf(src,
"void %s::set_implicit_omit()\n{\n"
"if (val_ptr == NULL) return;\n"
"for (int i = 0; i < val_ptr->n_elements; i++) {\n"
"if (val_ptr->value_elements[i] != NULL) val_ptr->value_elements[i]->set_implicit_omit();\n"
"}\n}\n\n", name);
/* encoding / decoding functions */
def = mputstr(def, "void encode_text(Text_Buf& text_buf) const;\n");
src = mputprintf(src,
"void %s::encode_text(Text_Buf& text_buf) const\n"
"{\n"
"if (val_ptr == NULL) "
"TTCN_error(\"Text encoder: Encoding an unbound value of type %s.\");\n"
"text_buf.push_int(val_ptr->n_elements);\n"
"for (int elem_count = 0; elem_count < val_ptr->n_elements; "
"elem_count++)\n"
"(*this)[elem_count].encode_text(text_buf);\n"
"}\n\n", name, dispname);
def = mputstr(def, "void decode_text(Text_Buf& text_buf);\n");
src = mputprintf(src,
"void %s::decode_text(Text_Buf& text_buf)\n"
"{\n"
"clean_up();\n"
"val_ptr = new recordof_setof_struct;\n"
"val_ptr->ref_count = 1;\n"
"val_ptr->n_elements = text_buf.pull_int().get_val();\n"
"if (val_ptr->n_elements < 0) TTCN_error(\"Text decoder: Negative size "
"was received for a value of type %s.\");\n"
"val_ptr->value_elements = (%s**)allocate_pointers(val_ptr->n_elements);\n"
"for (int elem_count = 0; elem_count < val_ptr->n_elements; "
"elem_count++) {\n"
"val_ptr->value_elements[elem_count] = new %s;\n"
"val_ptr->value_elements[elem_count]->decode_text(text_buf);\n"
"}\n"
if(ber_needed || raw_needed || text_needed || xer_needed || json_needed
|| oer_needed) {
def_encdec(name, &def, &src, ber_needed, raw_needed, text_needed,
xer_needed, json_needed, oer_needed, FALSE);
}
if(text_needed){
src=mputprintf(src,
"int %s::TEXT_encode(const TTCN_Typedescriptor_t& p_td,"
" TTCN_Buffer& p_buf) const{\n"
" int encoded_length=0;\n"
" if(p_td.text->begin_encode){\n"
" p_buf.put_cs(*p_td.text->begin_encode);\n"
" encoded_length+=p_td.text->begin_encode->lengthof();\n"
" }\n"
" if(val_ptr==NULL) {\n"
" TTCN_EncDec_ErrorContext::error\n"
" (TTCN_EncDec::ET_UNBOUND, \"Encoding an unbound value.\");\n"
" if(p_td.text->end_encode){\n"
" p_buf.put_cs(*p_td.text->end_encode);\n"
" encoded_length+=p_td.text->end_encode->lengthof();\n"
" }\n"
" return encoded_length;\n"
" }\n"
" if(a!=0 && p_td.text->separator_encode){\n"
" p_buf.put_cs(*p_td.text->separator_encode);\n"
" encoded_length+=p_td.text->separator_encode->lengthof();\n"
" }\n"
" encoded_length+=(*this)[a].TEXT_encode(*p_td.oftype_descr,p_buf);\n"
" }\n"
" if(p_td.text->end_encode){\n"
" p_buf.put_cs(*p_td.text->end_encode);\n"
" encoded_length+=p_td.text->end_encode->lengthof();\n"
" }\n"
" return encoded_length;\n"
"}\n"
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
);
src = mputprintf(src,
"int %s::TEXT_decode(const TTCN_Typedescriptor_t& p_td,"
" TTCN_Buffer& p_buf, Limit_Token_List& limit, boolean no_err"
", boolean first_call){\n"
" int decoded_length=0;\n"
" size_t pos=p_buf.get_pos();\n"
" boolean sep_found=FALSE;\n"
" int sep_length=0;\n"
" int ml=0;\n"
" if(p_td.text->begin_decode){\n"
" int tl;\n"
" if((tl=p_td.text->begin_decode->match_begin(p_buf))<0){\n"
" if(no_err)return -1;\n"
" TTCN_EncDec_ErrorContext::error\n"
" (TTCN_EncDec::ET_TOKEN_ERR, \"The specified token '%%s'"
" not found for '%%s': \",(const char*)*(p_td.text->begin_decode)"
", p_td.name);\n"
" return 0;\n"
" }\n"
" decoded_length+=tl;\n"
" p_buf.increase_pos(tl);\n"
" }\n"
" if(p_td.text->end_decode){\n"
" limit.add_token(p_td.text->end_decode);\n"
" ml++;\n"
" }\n"
" if(p_td.text->separator_decode){\n"
" limit.add_token(p_td.text->separator_decode);\n"
" ml++;\n"
" }\n"
" if(first_call) {\n"
" clean_up();\n"
" val_ptr=new recordof_setof_struct;\n"
" val_ptr->ref_count=1;\n"
" val_ptr->n_elements=0;\n"
" val_ptr->value_elements=NULL;\n"
" while(TRUE){\n"
" %s *val=new %s;\n"
" pos=p_buf.get_pos();\n"
" int len=val->TEXT_decode(*p_td.oftype_descr,p_buf,limit,TRUE);\n"
" if(len==-1 || (len==0 && !limit.has_token())){\n"
" p_buf.set_pos(pos);\n"
" delete val;\n"
" if(sep_found){\n"
" p_buf.set_pos(p_buf.get_pos()-sep_length);\n"
" decoded_length-=sep_length;\n"
" }\n"
" break;\n"
" }\n"
" sep_found=FALSE;\n"
"((void**)val_ptr->value_elements, val_ptr->n_elements, "
"val_ptr->n_elements + 1);\n"
" val_ptr->value_elements[val_ptr->n_elements]=val;\n"
" val_ptr->n_elements++;\n"
" decoded_length+=len;\n"
" if(p_td.text->separator_decode){\n"
" int tl;\n"
" if((tl=p_td.text->separator_decode->match_begin(p_buf))<0){\n"
" break;\n"
" }\n"
" decoded_length+=tl;\n"
" p_buf.increase_pos(tl);\n"
" sep_length=tl;\n"
" sep_found=TRUE;\n"
" } else if(p_td.text->end_decode){\n"
" int tl;\n"
" if((tl=p_td.text->end_decode->match_begin(p_buf))!=-1){\n"
" decoded_length+=tl;\n"
" p_buf.increase_pos(tl);\n"
" limit.remove_tokens(ml);\n"
" return decoded_length;\n"
" }\n"
" } else if(limit.has_token(ml)){\n"
" if(limit.match(p_buf,ml)==0){\n"
" sep_found=FALSE;\n"
" break;\n"
" }\n"
" }\n"
" }\n"
);
src = mputstr(src,
" limit.remove_tokens(ml);\n"
" if(p_td.text->end_decode){\n"
" int tl;\n"
" if((tl=p_td.text->end_decode->match_begin(p_buf))<0){\n"
" for(int a=more; a<val_ptr->n_elements; a++) "
"delete val_ptr->value_elements[a];\n"
" val_ptr->n_elements=more;\n"
" }\n"
" return -1;\n"
" }\n"
" TTCN_EncDec_ErrorContext::error"
"(TTCN_EncDec::ET_TOKEN_ERR, \"The specified token '%s'"
" not found for '%s': \",(const char*)*(p_td.text->end_decode)"
",p_td.name);\n"
" return decoded_length;\n"
" }\n"
" decoded_length+=tl;\n"
" p_buf.increase_pos(tl);\n"
" }\n"
" if(!(p_td.text->end_decode || p_td.text->begin_decode)) {\n"
" if(no_err)return -1;\n"
" TTCN_EncDec_ErrorContext::error"
"(TTCN_EncDec::ET_TOKEN_ERR, \"No record/set of member found.\");\n"
" return decoded_length;\n"
" }\n"
" }\n"
"!(p_td.text->end_decode || p_td.text->begin_decode)) return -1;\n"
" return decoded_length;\n"
"}\n"
);
}
/* BER functions */
if(ber_needed) {
/* BER_encode_TLV() */
src=mputprintf
(src,
"ASN_BER_TLV_t* %s::BER_encode_TLV(const TTCN_Typedescriptor_t&"
" p_td, unsigned p_coding) const\n"
"{\n"
" BER_chk_descr(p_td);\n"
" ASN_BER_TLV_t *new_tlv=BER_encode_chk_bound(is_bound());\n"
" if(!new_tlv) {\n"
" new_tlv=ASN_BER_TLV_t::construct(NULL);\n"
" TTCN_EncDec_ErrorContext ec;\n"
" for(int elem_i=0; elem_i<val_ptr->n_elements; elem_i++) {\n"
" ec.set_msg(\"Component #%%d: \", elem_i);\n"
" new_tlv->add_TLV((*this)[elem_i].BER_encode_TLV"
" }\n"
"%s"
" }\n"
" new_tlv=ASN_BER_V2TLV(new_tlv, p_td, p_coding);\n"
" return new_tlv;\n"
"}\n"
"\n"
/* BER_decode_TLV() */
"boolean %s::BER_decode_TLV(const TTCN_Typedescriptor_t& p_td,"
" const ASN_BER_TLV_t& p_tlv, unsigned L_form)\n"
"{\n"
" BER_chk_descr(p_td);\n"
" ASN_BER_TLV_t stripped_tlv;\n"
" BER_decode_strip_tags(*p_td.ber, p_tlv, L_form, stripped_tlv);\n"
" TTCN_EncDec_ErrorContext ec_0(\"While decoding '%%s' type: \","
" p_td.name);\n"
" stripped_tlv.chk_constructed_flag(TRUE);\n"
" clean_up();\n"
" val_ptr = new recordof_setof_struct;\n"
" val_ptr->ref_count = 1;\n"
" val_ptr->n_elements = 0;\n"
" val_ptr->value_elements = NULL;\n"
" size_t V_pos=0;\n"
" ASN_BER_TLV_t tmp_tlv;\n"
" TTCN_EncDec_ErrorContext ec_1(\"Component #\");\n"
" TTCN_EncDec_ErrorContext ec_2(\"0: \");\n"
" while(BER_decode_constdTLV_next(stripped_tlv, V_pos, L_form, "
"tmp_tlv)) {\n"
" val_ptr->value_elements = (%s**)reallocate_pointers("
"(void**)val_ptr->value_elements, val_ptr->n_elements, "
"val_ptr->n_elements + 1);\n"
" val_ptr->n_elements++;\n"
" val_ptr->value_elements[val_ptr->n_elements - 1] = new %s;\n"
" val_ptr->value_elements[val_ptr->n_elements - 1]->BER_decode_TLV(*p_td.oftype_descr, tmp_tlv, "
" }\n"
" return TRUE;\n"
"}\n"
"\n"
, sdef->kind==SET_OF?" new_tlv->sort_tlvs();\n":""
);
if(sdef->has_opentypes) {
/* BER_decode_opentypes() */
def=mputstr
(def,
"void BER_decode_opentypes(TTCN_Type_list& p_typelist,"
" unsigned L_form);\n");
src=mputprintf
(src,
"void %s::BER_decode_opentypes(TTCN_Type_list& p_typelist,"
" unsigned L_form)\n"
"{\n"
" p_typelist.push(this);\n"
" TTCN_EncDec_ErrorContext ec_0(\"Component #\");\n"
" TTCN_EncDec_ErrorContext ec_1;\n"
" for(int elem_i=0; elem_i<val_ptr->n_elements; elem_i++) {\n"
" val_ptr->value_elements[elem_i]->BER_decode_opentypes(p_typelist,"
" L_form);\n"
" }\n"
" p_typelist.pop();\n"
"}\n"
"\n"
, name
);
}
}
if(raw_needed){
src=mputprintf(src,
"int %s::RAW_decode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf, "
"int limit, raw_order_t top_bit_ord, boolean /*no_err*/, int sel_field"
", boolean first_call, const RAW_Force_Omit*){\n"
" int prepaddlength=p_buf.increase_pos_padd(p_td.raw->prepadding);\n"
" limit-=prepaddlength;\n"
" int decoded_length=0;\n"
" int decoded_field_length=0;\n"
" size_t start_of_field=0;\n"
" if(first_call) {\n"
" clean_up();\n"
" val_ptr=new recordof_setof_struct;\n"
" val_ptr->ref_count=1;\n"
" val_ptr->n_elements=0;\n"
" val_ptr->value_elements=NULL;\n"
" if(p_td.raw->fieldlength || sel_field!=-1){\n"
" int a=0;\n"
" if(sel_field==-1) sel_field=p_td.raw->fieldlength;\n"
" start_of_field=p_buf.get_pos_bit();\n"
" decoded_field_length=(*this)[a+start_field].RAW_decode(*p_td.oftype_descr,"
" if(decoded_field_length < 0){\n"
" while(a>=0){\n"
" delete &(*this)[a+start_field];\n"
" a--;\n"
" val_ptr->n_elements--;\n"
" }\n"
" p_buf.set_pos_bit(start_of_field);\n"
" return decoded_field_length;\n"
" }\n"
" decoded_length+=decoded_field_length;\n"
" limit-=decoded_field_length;\n"
" }\n"
" } else {\n"
" if(limit==0){\n"
" if(!first_call) return -1;\n"
" return decoded_length+p_buf.increase_pos_padd(p_td.raw->padding)"