Sync with 5.3.0
[deliverable/titan.core.git] / compiler2 / record_of.c
CommitLineData
970ed795
EL
1///////////////////////////////////////////////////////////////////////////////
2// Copyright (c) 2000-2014 Ericsson Telecom AB
3// All rights reserved. This program and the accompanying materials
4// are made available under the terms of the Eclipse Public License v1.0
5// which accompanies this distribution, and is available at
6// http://www.eclipse.org/legal/epl-v10.html
7///////////////////////////////////////////////////////////////////////////////
8#include "../common/memory.h"
9#include "datatypes.h"
10#include "record_of.h"
11#include "encdec.h"
12
13#include "main.hh"
14#include "ttcn3/compiler.h"
15
16/** code generation for original runtime */
17static void defRecordOfClass1(const struct_of_def *sdef, output_struct *output);
18static void defRecordOfTemplate1(const struct_of_def *sdef, output_struct *output);
19/** code generation for alternative runtime (TITAN_RUNTIME_2) */
20static void defRecordOfClass2(const struct_of_def *sdef, output_struct *output);
21static void defRecordOfTemplate2(const struct_of_def *sdef, output_struct *output);
22
23void defRecordOfClass(const struct_of_def *sdef, output_struct *output)
24{
25 if (use_runtime_2) defRecordOfClass2(sdef, output);
26 else defRecordOfClass1(sdef, output);
27}
28
29void defRecordOfTemplate(const struct_of_def *sdef, output_struct *output)
30{
31 if (use_runtime_2) defRecordOfTemplate2(sdef, output);
32 else defRecordOfTemplate1(sdef, output);
33}
34
35/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
36
37void defRecordOfClass1(const struct_of_def *sdef, output_struct *output)
38{
39 char *def = NULL, *src = NULL;
40 const char *name = sdef->name, *dispname = sdef->dispname;
41 const char *type = sdef->type;
a38c6d4c 42 boolean ber_needed = force_gen_seof || (sdef->isASN1 && enable_ber());
43 boolean raw_needed = force_gen_seof || (sdef->hasRaw && enable_raw());
44 boolean text_needed = force_gen_seof || (sdef->hasText && enable_text());
45 boolean xer_needed = force_gen_seof || (sdef->hasXer && enable_xer());
46 boolean json_needed = force_gen_seof || (sdef->hasJson && enable_json());
970ed795
EL
47
48 /* Class definition and private data members */
49 def = mputprintf(def,
50#ifndef NDEBUG
51 "// written by %s in " __FILE__ " at %d\n"
52#endif
53 "class %s : public Base_Type {\n"
54 "struct recordof_setof_struct {\n"
55 "int ref_count;\n"
56 "int n_elements;\n"
57 "%s **value_elements;\n"
58 "} *val_ptr;\n"
970ed795
EL
59#ifndef NDEBUG
60 , __FUNCTION__, __LINE__
61#endif
62 , name, type);
63
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);
67
68 /* private member functions */
69 def = mputprintf(def,
70 "private:\n"
71 "friend boolean operator==(null_type null_value, "
72 "const %s& other_value);\n", name);
73
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"
82 "{\n"
83 "if (((const %s*)left_ptr)->val_ptr == NULL) "
84 "TTCN_error(\"The left operand of comparison is an unbound value of "
85 "type %s.\");\n"
86 "if (((const %s*)right_ptr)->val_ptr == NULL) "
87 "TTCN_error(\"The right operand of comparison is an unbound value of "
88 "type %s.\");\n"
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"
94 "} else {\n"
95 "return ((const %s*)right_ptr)->val_ptr->value_elements[right_index] == NULL;\n"
96 "}\n"
97 "}\n\n", name, name, dispname, name, dispname, name, name, name, name, name);
98 }
970ed795
EL
99
100 /* public member functions */
101 def = mputstr(def, "\npublic:\n");
102 def = mputprintf(def, " typedef %s of_type;\n", sdef->type);
103
104 /* constructors */
105 def = mputprintf(def, "%s();\n", name);
106 src = mputprintf(src,
107 "%s::%s()\n"
108 "{\n"
109 "val_ptr = NULL;\n"
970ed795
EL
110 "}\n\n", name, name);
111
112 def = mputprintf(def, "%s(null_type other_value);\n", name);
113 src = mputprintf(src,
114 "%s::%s(null_type)\n"
115 "{\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"
970ed795
EL
120 "}\n\n", name, name);
121
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"
126 "{\n"
127 "if (!other_value.is_bound()) "
128 "TTCN_error(\"Copying an unbound value of type %s.\");\n"
970ed795
EL
129 "val_ptr = other_value.val_ptr;\n"
130 "val_ptr->ref_count++;\n"
af710487 131 "}\n\n", name, name, name, dispname);
970ed795
EL
132
133 /* destructor */
134 def = mputprintf(def, "~%s();\n\n", name);
135 src = mputprintf(src,
136 "%s::~%s()\n"
137 "{\n"
138 "clean_up();\n"
139 "if (val_ptr != NULL) val_ptr = NULL;\n"
140 "}\n\n", name, name);
141
142 /* clean_up function */
143 def = mputstr(def, "void clean_up();\n");
144 src = mputprintf
145 (src,
146 "void %s::clean_up()\n"
147 "{\n"
148 "if (val_ptr != NULL) {\n"
149 "if (val_ptr->ref_count > 1) {\n"
150 "val_ptr->ref_count--;\n"
151 "val_ptr = NULL;\n"
152 "}\n"
153 "else if (val_ptr->ref_count == 1) {\n"
970ed795
EL
154 "for (int elem_count = 0; elem_count < val_ptr->n_elements;\n"
155 "elem_count++)\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"
159 "delete val_ptr;\n"
160 "val_ptr = NULL;\n"
161 "}\n"
970ed795
EL
162 "else\n"
163 "TTCN_error(\"Internal error: Invalid reference counter in a record "
164 "of/set of value.\");\n"
165 "}\n"
166 "}\n\n", name);
167
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"
172 "{\n"
af710487 173 "clean_up();\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"
970ed795
EL
178 "return *this;\n"
179 "}\n\n", name, name);
180
181 def = mputprintf(def, "%s& operator=(const %s& other_value);\n\n",
182 name, name);
183 src = mputprintf(src,
184 "%s& %s::operator=(const %s& other_value)\n"
185 "{\n"
af710487 186 "if (other_value.val_ptr == NULL) "
970ed795
EL
187 "TTCN_error(\"Assigning an unbound value of type %s.\");\n"
188 "if (this != &other_value) {\n"
970ed795
EL
189 "clean_up();\n"
190 "val_ptr = other_value.val_ptr;\n"
191 "val_ptr->ref_count++;\n"
192 "}\n"
970ed795 193 "return *this;\n"
af710487 194 "}\n\n", name, name, name, dispname);
970ed795
EL
195
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"
200 "{\n"
201 "if (val_ptr == NULL)\n"
202 "TTCN_error(\"The left operand of comparison is an unbound value of "
203 "type %s.\");\n"
af710487 204 "return val_ptr->n_elements == 0 ;\n"
970ed795
EL
205 "}\n\n", name, dispname);
206
207 def = mputprintf(def, "boolean operator==(const %s& other_value) const;\n",
208 name);
209 src = mputprintf(src,
210 "boolean %s::operator==(const %s& other_value) const\n"
211 "{\n"
212 "if (val_ptr == NULL) "
213 "TTCN_error(\"The left operand of comparison is an unbound value of type "
214 "%s.\");\n"
215 "if (other_value.val_ptr == NULL) "
216 "TTCN_error(\"The right operand of comparison is an unbound value of type "
217 "%s.\");\n"
218 "if (val_ptr == other_value.val_ptr) return TRUE;\n", name, name,
219 dispname, dispname);
220 if (sdef->kind == SET_OF) {
221 src = mputstr(src,
af710487 222 "return compare_set_of(this, val_ptr->n_elements, &other_value, "
223 "(other_value.val_ptr)->n_elements, compare_function);\n");
970ed795
EL
224 } else {
225 src = mputstr
226 (src,
af710487 227 "if (val_ptr->n_elements != (other_value.val_ptr)->n_elements)\n"
970ed795 228 "return FALSE;\n"
af710487 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"
970ed795
EL
232 " if (*val_ptr->value_elements[elem_count] != "
233 "*(other_value.val_ptr)->value_elements[elem_count]) "
234 "return FALSE;\n"
235 "} else return FALSE;\n"
236 "} else {\n"
af710487 237 "if ((other_value.val_ptr)->value_elements[elem_count] != NULL) "
238 "return FALSE;\n"
970ed795
EL
239 "}\n"
240 "}\n"
241 "return TRUE;\n");
242 }
243 src = mputstr(src, "}\n\n");
244
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);
249
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"
255 "{\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; "
271 "elem_count++){\n"
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"
275 "}\n"
276 "}\n"
277 "clean_up();\n"
278 "val_ptr = new_val_ptr;\n"
279 "}\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"
283 "}\n"
284 "return *val_ptr->value_elements[index_value];\n"
285 "}\n\n", type, name, dispname, type, type, type);
286
287 def = mputprintf(def, "%s& operator[](const INTEGER& index_value);\n",
288 type);
289 src = mputprintf(src,
290 "%s& %s::operator[](const INTEGER& index_value)\n"
291 "{\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);
296
297 /* Const operator[] throws an error if over-indexing */
298 def = mputprintf(def, "const %s& operator[](int index_value) const;\n",
299 type);
300 src = mputprintf(src,
301 "const %s& %s::operator[](int index_value) const\n"
302 "{\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"
af710487 307 "if (index_value >= val_ptr->n_elements) TTCN_error(\"Index overflow in "
970ed795 308 "a value of type %s: The index is %%d, but the value has only %%d "
af710487 309 "elements.\", index_value, val_ptr->n_elements);\n"
970ed795
EL
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);
313
314 def = mputprintf(def, "const %s& operator[](const INTEGER& index_value) "
315 "const;\n\n", type);
316 src = mputprintf(src,
317 "const %s& %s::operator[](const INTEGER& index_value) const\n"
318 "{\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);
323
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"
333 "{\n"
334 "return *this >>= (-rotate_count);\n"
335 "}\n\n"
336 "%s %s::operator<<=(const INTEGER& rotate_count) const\n"
337 "{\n"
338 "rotate_count.must_bound(\""
339 "Unbound integer operand of rotate left operator.\");\n"
340 "return *this >>= (int)(-rotate_count);\n"
341 "}\n\n"
342 "%s %s::operator>>=(const INTEGER& rotate_count) const\n"
343 "{\n"
344 "rotate_count.must_bound(\""
345 "Unbound integer operand of rotate right operator.\");\n"
346 "return *this >>= (int)rotate_count;\n"
347 "}\n\n"
348 "%s %s::operator>>=(int rotate_count) const\n"
349 "{\n"
350 "if (val_ptr == NULL) "
351 "TTCN_error(\"Performing rotation operation on an unbound value of type "
352 "%s.\");\n"
af710487 353 "if (val_ptr->n_elements == 0) return *this;\n"
970ed795 354 "int rc;\n"
af710487 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"
970ed795
EL
357 "if (rc == 0) return *this;\n"
358 "%s ret_val;\n"
af710487 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] ="
970ed795
EL
363 "new %s(*val_ptr->value_elements[i]);\n"
364 "}\n"
365 "}\n"
366 "return ret_val;\n"
367 "}\n\n",
368 name, name, name, name, name, name, name, name, dispname, name, type);
369
370 /* concatenation */
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"
375 "{\n"
376 "if (val_ptr == NULL || other_value.val_ptr == NULL) "
377 "TTCN_error(\"Unbound operand of %s concatenation.\");\n"
af710487 378 "if (val_ptr->n_elements == 0) return other_value;\n"
379 "if (other_value.val_ptr->n_elements == 0) return *this;\n"
970ed795 380 "%s ret_val;\n"
af710487 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"
970ed795
EL
384 "ret_val.val_ptr->value_elements[i] = new %s(*val_ptr->value_elements[i]);\n"
385 "}\n"
386 "}\n"
af710487 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] = "
970ed795
EL
390 "new %s(*other_value.val_ptr->value_elements[i]);\n"
391 "}\n"
392 "}\n"
393 "return ret_val;\n"
394 "}\n\n", name, name, name, dispname, name, type, type);
395
396 /* substr() */
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"
401 "{\n"
402 "if (val_ptr == NULL) "
403 "TTCN_error(\"The first argument of substr() is an unbound value of "
404 "type %s.\");\n"
af710487 405 "check_substr_arguments(val_ptr->n_elements, index, returncount, "
970ed795
EL
406 "\"%s\",\"element\");\n"
407 "%s ret_val;\n"
408 "ret_val.set_size(returncount);\n"
409 "for (int i=0; i<returncount; i++) {\n"
af710487 410 "if (val_ptr->value_elements[i+index] != NULL) {\n"
970ed795
EL
411 "ret_val.val_ptr->value_elements[i] = "
412 "new %s(*val_ptr->value_elements[i+index]);\n"
413 "}\n"
414 "}\n"
415 "return ret_val;\n"
416 "}\n\n", name, name, dispname, dispname, name, type);
417
418 /* replace() */
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"
423 "{\n"
424 "if (val_ptr == NULL) "
425 "TTCN_error(\"The first argument of replace() is an unbound value of "
426 "type %s.\");\n"
427 "if (repl.val_ptr == NULL) "
428 "TTCN_error(\"The fourth argument of replace() is an unbound value of "
429 "type %s.\");\n"
af710487 430 "check_replace_arguments(val_ptr->n_elements, index, len, "
970ed795
EL
431 "\"%s\",\"element\");\n"
432 "%s ret_val;\n"
af710487 433 "ret_val.set_size(val_ptr->n_elements + repl.val_ptr->n_elements - len);\n"
970ed795 434 "for (int i = 0; i < index; i++) {\n"
af710487 435 "if (val_ptr->value_elements[i] != NULL) {\n"
970ed795
EL
436 "ret_val.val_ptr->value_elements[i] = new %s(*val_ptr->value_elements[i]);\n"
437 "}\n"
438 "}\n"
af710487 439 "for (int i = 0; i < repl.val_ptr->n_elements; i++) {\n"
440 "if (repl.val_ptr->value_elements[i] != NULL) {\n"
970ed795
EL
441 "ret_val.val_ptr->value_elements[i+index] = "
442 "new %s(*repl.val_ptr->value_elements[i]);\n"
443 "}\n"
444 "}\n"
af710487 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] = "
970ed795
EL
448 "new %s(*val_ptr->value_elements[index+i+len]);\n"
449 "}\n"
450 "}\n"
451 "return ret_val;\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",
455 name, name);
456 src = mputprintf(src,
457 "%s %s::replace(int index, int len, const %s_template& repl) const\n"
458 "{\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);
463
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"
467 "{\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; "
483 "elem_count++) {\n"
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"
487 "}\n"
488 "}\n"
489 "clean_up();\n"
490 "val_ptr = new_val_ptr;\n"
491 "}\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"
499 "#endif\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; "
af710487 503 "elem_count++)\n"
504 "if (val_ptr->value_elements[elem_count] != NULL)"
970ed795 505 "delete val_ptr->value_elements[elem_count];\n"
970ed795
EL
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"
510 "}\n"
970ed795
EL
511 "}\n\n", name, dispname, type, type, type, dispname, type);
512
513 /* is_bound function */
514 def = mputstr(def,
af710487 515 "inline boolean is_bound() const {return val_ptr != NULL; }\n");
970ed795
EL
516
517 /* is_present function */
518 def = mputstr(def,
519 "inline boolean is_present() const { return is_bound(); }\n");
520
521 /* is_value function */
522 def = mputstr(def,
523 "boolean is_value() const;\n");
524 src = mputprintf(src,
525 "boolean %s::is_value() const\n"
526 "{\n"
527 "if (val_ptr == NULL) return false;\n"
af710487 528 "for(int i = 0; i < val_ptr->n_elements; ++i) {\n"
529 "if (val_ptr->value_elements[i] == NULL || "
970ed795
EL
530 "!val_ptr->value_elements[i]->is_value()) return FALSE;\n"
531 "}\n"
532 "return TRUE;\n"
533 "}\n\n", name);
534
535 /* sizeof operation */
536 def = mputstr(def,
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"
541 "{\n"
542 "if (val_ptr == NULL) "
543 "TTCN_error(\"Performing sizeof operation on an unbound value of type "
544 "%s.\");\n"
af710487 545 "return val_ptr->n_elements;\n"
970ed795
EL
546 "}\n\n", name, dispname);
547
548 /* lengthof operation */
549 def = mputstr(def, "int lengthof() const;\n");
550 src = mputprintf(src,
551 "int %s::lengthof() const\n"
552 "{\n"
553 "if (val_ptr == NULL) "
554 "TTCN_error(\"Performing lengthof operation on an unbound value of type "
555 "%s.\");\n"
af710487 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"
970ed795
EL
558 "return 0;\n"
559 "}\n\n", name, dispname);
560
561 /* log function */
562 def = mputstr(def, "void log() const;\n");
563 src = mputprintf
564 (src,
565 "void %s::log() const\n"
566 "{\n"
567 "if (val_ptr == NULL) {;\n"
568 "TTCN_Logger::log_event_unbound();\n"
569 "return;\n"
570 "}\n"
af710487 571 "switch (val_ptr->n_elements) {\n"
970ed795
EL
572 "case 0:\n"
573 "TTCN_Logger::log_event_str(\"{ }\");\n"
574 "break;\n"
575 "default:\n"
576 "TTCN_Logger::log_event_str(\"{ \");\n"
af710487 577 "for (int elem_count = 0; elem_count < val_ptr->n_elements; "
970ed795
EL
578 "elem_count++) {\n"
579 "if (elem_count > 0) TTCN_Logger::log_event_str(\", \");\n"
580 "(*this)[elem_count].log();\n"
581 "}\n"
582 "TTCN_Logger::log_event_str(\" }\");\n"
583 "}\n"
584 "}\n\n", name);
585
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"
590 "{\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"
599 " }\n"
600 " int param_index = -1;\n"
601 " sscanf(param_field, \"%%d\", &param_index);\n"
602 " (*this)[param_index].set_param(param);\n"
603 " return;\n"
604 " }\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"
610 " return;\n"
611 " }\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"
619 " }\n"
620 " }\n"
621 " break;\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"
626 " }\n"
627 " break;\n"
628 " default:\n"
629 " param.type_error(\"%s value\", \"%s\");\n"
630 " }\n"
631 " break;\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"
641 " }\n"
642 " }\n"
643 " } break;\n"
644 " case Module_Param::MP_Indexed_List:\n"
645 " param.error(\"Cannot concatenate an indexed value list\");\n"
646 " break;\n"
647 " default:\n"
648 " param.type_error(\"%s value\", \"%s\");\n"
649 " }\n"
650 " break;\n"
651 " default:\n"
652 " TTCN_error(\"Internal error: Unknown operation type.\");\n"
653 " }\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);
658
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"
af710487 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"
970ed795 666 "}\n}\n\n", name);
970ed795
EL
667
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"
672 "{\n"
673 "if (val_ptr == NULL) "
674 "TTCN_error(\"Text encoder: Encoding an unbound value of type %s.\");\n"
af710487 675 "text_buf.push_int(val_ptr->n_elements);\n"
676 "for (int elem_count = 0; elem_count < val_ptr->n_elements; "
970ed795
EL
677 "elem_count++)\n"
678 "(*this)[elem_count].encode_text(text_buf);\n"
679 "}\n\n", name, dispname);
680
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"
684 "{\n"
af710487 685 "clean_up();\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 "
970ed795 690 "was received for a value of type %s.\");\n"
af710487 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; "
970ed795 693 "elem_count++) {\n"
970ed795 694 "val_ptr->value_elements[elem_count] = new %s;\n"
970ed795
EL
695 "val_ptr->value_elements[elem_count]->decode_text(text_buf);\n"
696 "}\n"
af710487 697 "}\n\n", name, dispname, type, type);
970ed795
EL
698
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);
702
703 if(text_needed){
704 src=mputprintf(src,
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"
711 " }\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"
718 " }\n"
719 " return encoded_length;\n"
720 " }\n"
af710487 721 " for(int a=0;a<val_ptr->n_elements;a++){\n"
970ed795
EL
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"
725 " }\n"
a38c6d4c 726 " encoded_length+=(*this)[a].TEXT_encode(*p_td.oftype_descr,p_buf);\n"
970ed795
EL
727 " }\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"
731 " }\n"
732 " return encoded_length;\n"
733 "}\n"
a38c6d4c 734 ,name
970ed795
EL
735 );
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"
744 " int ml=0;\n"
745 " if(p_td.text->begin_decode){\n"
746 " int tl;\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)"
752 ", p_td.name);\n"
753 " return 0;\n"
754 " }\n"
755 " decoded_length+=tl;\n"
756 " p_buf.increase_pos(tl);\n"
757 " }\n"
758 " if(p_td.text->end_decode){\n"
759 " limit.add_token(p_td.text->end_decode);\n"
760 " ml++;\n"
761 " }\n"
762 " if(p_td.text->separator_decode){\n"
763 " limit.add_token(p_td.text->separator_decode);\n"
764 " ml++;\n"
765 " }\n"
766 " if(first_call) {\n"
af710487 767 " clean_up();\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"
970ed795 772 " }\n"
af710487 773 " int more=val_ptr->n_elements;\n"
970ed795
EL
774 " while(TRUE){\n"
775 " %s *val=new %s;\n"
776 " pos=p_buf.get_pos();\n"
a38c6d4c 777 " int len=val->TEXT_decode(*p_td.oftype_descr,p_buf,limit,TRUE);\n"
970ed795
EL
778 " if(len==-1 || (len==0 && !limit.has_token())){\n"
779 " p_buf.set_pos(pos);\n"
780 " delete val;\n"
781 " if(sep_found){\n"
782 " p_buf.set_pos(p_buf.get_pos()-sep_length);\n"
783 " decoded_length-=sep_length;\n"
784 " }\n"
785 " break;\n"
786 " }\n"
787 " sep_found=FALSE;\n"
af710487 788 " val_ptr->value_elements = (%s**)reallocate_pointers"
970ed795
EL
789 "((void**)val_ptr->value_elements, val_ptr->n_elements, "
790 "val_ptr->n_elements + 1);\n"
af710487 791 " val_ptr->value_elements[val_ptr->n_elements]=val;\n"
792 " val_ptr->n_elements++;\n"
970ed795
EL
793 " decoded_length+=len;\n"
794 " if(p_td.text->separator_decode){\n"
795 " int tl;\n"
796 " if((tl=p_td.text->separator_decode->match_begin(p_buf))<0){\n"
797 " break;\n"
798 " }\n"
799 " decoded_length+=tl;\n"
800 " p_buf.increase_pos(tl);\n"
801 " sep_length=tl;\n"
802 " sep_found=TRUE;\n"
803 " } else if(p_td.text->end_decode){\n"
804 " int tl;\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"
810 " }\n"
811 " } else if(limit.has_token(ml)){\n"
812 " int tl;\n"
813 " if((tl=limit.match(p_buf,ml))==0){\n"
814 " sep_found=FALSE;\n"
815 " break;\n"
816 " }\n"
817 " }\n"
818 " }\n"
a38c6d4c 819 ,name,type,type,type
970ed795
EL
820 );
821 src = mputstr(src,
822 " limit.remove_tokens(ml);\n"
823 " if(p_td.text->end_decode){\n"
824 " int tl;\n"
825 " if((tl=p_td.text->end_decode->match_begin(p_buf))<0){\n"
826 " if(no_err){"
827 " if(!first_call){\n"
af710487 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"
970ed795
EL
831 " }\n"
832 " return -1;\n"
833 " }\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)"
837 ",p_td.name);\n"
838 " return decoded_length;\n"
839 " }\n"
840 " decoded_length+=tl;\n"
841 " p_buf.increase_pos(tl);\n"
842 " }\n"
af710487 843 " if(val_ptr->n_elements==0){\n"
970ed795
EL
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"
849 " }\n"
850 " }\n"
af710487 851 " if(!first_call && more==val_ptr->n_elements && "
970ed795
EL
852 "!(p_td.text->end_decode || p_td.text->begin_decode)) return -1;\n"
853 " return decoded_length;\n"
854 "}\n"
855 );
856 }
857
858 /* BER functions */
859 if(ber_needed) {
860 /* BER_encode_TLV() */
861 src=mputprintf
862 (src,
863 "ASN_BER_TLV_t* %s::BER_encode_TLV(const TTCN_Typedescriptor_t&"
864 " p_td, unsigned p_coding) const\n"
865 "{\n"
866 " BER_chk_descr(p_td);\n"
867 " ASN_BER_TLV_t *new_tlv=BER_encode_chk_bound(is_bound());\n"
868 " if(!new_tlv) {\n"
869 " new_tlv=ASN_BER_TLV_t::construct(NULL);\n"
870 " TTCN_EncDec_ErrorContext ec;\n"
af710487 871 " for(int elem_i=0; elem_i<val_ptr->n_elements; elem_i++) {\n"
970ed795
EL
872 " ec.set_msg(\"Component #%%d: \", elem_i);\n"
873 " new_tlv->add_TLV((*this)[elem_i].BER_encode_TLV"
a38c6d4c 874 "(*p_td.oftype_descr, p_coding));\n"
970ed795
EL
875 " }\n"
876 "%s"
877 " }\n"
878 " new_tlv=ASN_BER_V2TLV(new_tlv, p_td, p_coding);\n"
879 " return new_tlv;\n"
880 "}\n"
881 "\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"
885 "{\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: \","
890 " p_td.name);\n"
891 " stripped_tlv.chk_constructed_flag(TRUE);\n"
af710487 892 " clean_up();\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"
970ed795
EL
897 " size_t V_pos=0;\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, "
902 "tmp_tlv)) {\n"
af710487 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"
a38c6d4c 908 " val_ptr->value_elements[val_ptr->n_elements - 1]->BER_decode_TLV(*p_td.oftype_descr, tmp_tlv, "
970ed795 909 "L_form);\n"
af710487 910 " ec_2.set_msg(\"%%d: \", val_ptr->n_elements);\n"
970ed795
EL
911 " }\n"
912 " return TRUE;\n"
913 "}\n"
914 "\n"
a38c6d4c 915 , name
970ed795 916 , sdef->kind==SET_OF?" new_tlv->sort_tlvs();\n":""
a38c6d4c 917 , name, type, type
970ed795
EL
918 );
919
920 if(sdef->has_opentypes) {
921 /* BER_decode_opentypes() */
922 def=mputstr
923 (def,
924 "void BER_decode_opentypes(TTCN_Type_list& p_typelist,"
925 " unsigned L_form);\n");
926 src=mputprintf
927 (src,
928 "void %s::BER_decode_opentypes(TTCN_Type_list& p_typelist,"
929 " unsigned L_form)\n"
930 "{\n"
931 " p_typelist.push(this);\n"
932 " TTCN_EncDec_ErrorContext ec_0(\"Component #\");\n"
933 " TTCN_EncDec_ErrorContext ec_1;\n"
af710487 934 " for(int elem_i=0; elem_i<val_ptr->n_elements; elem_i++) {\n"
970ed795 935 " ec_1.set_msg(\"%%d: \", elem_i);\n"
af710487 936 " val_ptr->value_elements[elem_i]->BER_decode_opentypes(p_typelist,"
970ed795
EL
937 " L_form);\n"
938 " }\n"
939 " p_typelist.pop();\n"
940 "}\n"
941 "\n"
942 , name
943 );
944 }
945 }
946
947 if(raw_needed){
948 src=mputprintf(src,
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"
af710487 958 " clean_up();\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"
970ed795 963 " }\n"
af710487 964 " int start_field=val_ptr->n_elements;\n"
970ed795
EL
965 " if(p_td.raw->fieldlength || sel_field!=-1){\n"
966 " int a=0;\n"
967 " if(sel_field==-1) sel_field=p_td.raw->fieldlength;\n"
968 " for(a=0;a<sel_field;a++){\n"
a38c6d4c 969 " decoded_field_length=(*this)[a+start_field].RAW_decode(*p_td.oftype_descr,"
970ed795
EL
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"
974 " }\n"
af710487 975 " if(a==0) val_ptr->n_elements=0;\n"
970ed795
EL
976 " } else {\n"
977 " int a=start_field;\n"
978 " if(limit==0){\n"
979 " if(!first_call) return -1;\n"
af710487 980 " val_ptr->n_elements=0;\n"
970ed795
EL
981 " return decoded_length+p_buf.increase_pos_padd(p_td.raw->padding)"
982 "+prepaddlength;\n"
983 " }\n"
984 " while(limit>0){\n"
985 " start_of_field=p_buf.get_pos_bit();\n"
a38c6d4c 986 " decoded_field_length=(*this)[a].RAW_decode(*p_td.oftype_descr,p_buf,limit,"
970ed795
EL
987 "top_bit_ord,TRUE);\n"
988 " if(decoded_field_length < 0){\n"
af710487 989 " delete &(*this)[a];\n"
990 " val_ptr->n_elements--;\n"
970ed795
EL
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)"
994 "+prepaddlength;\n"
995 " } else return -1;\n"
996 " }\n"
997 " decoded_length+=decoded_field_length;\n"
998 " limit-=decoded_field_length;\n"
999 " a++;\n"
a38c6d4c 1000 ,name
970ed795 1001 );
a38c6d4c 1002 if (force_gen_seof || (sdef->raw.extension_bit!=XDEFNO && sdef->raw.extension_bit!=XDEFDEFAULT)){
970ed795 1003 src=mputprintf(src,
a38c6d4c 1004 " if (%s%sp_buf.get_last_bit()%s)\n"
970ed795 1005 " return decoded_length+p_buf.increase_pos_padd(p_td.raw->padding)"
a38c6d4c 1006 "+prepaddlength;\n"
1007 , force_gen_seof ? "EXT_BIT_NO != p_td.raw->extension_bit && ((EXT_BIT_YES != p_td.raw->extension_bit) ^ " : ""
1008 , (force_gen_seof || sdef->raw.extension_bit == XDEFYES) ? "" : "!"
1009 , force_gen_seof ? ")" : "");
970ed795
EL
1010 }
1011 src=mputprintf(src,
1012 " }\n"
1013 " }\n"
1014 " return decoded_length+p_buf.increase_pos_padd(p_td.raw->padding)"
1015 "+prepaddlength;\n"
1016 "}\n\n"
1017 "int %s::RAW_encode(const TTCN_Typedescriptor_t& p_td,"
1018 "RAW_enc_tree& myleaf) const{\n"
1019 " int encoded_length=0;\n"
1020 " int encoded_num_of_records=p_td.raw->fieldlength?"
af710487 1021 "smaller(val_ptr->n_elements, p_td.raw->fieldlength)"
1022 ":val_ptr->n_elements;\n"
970ed795
EL
1023 " myleaf.isleaf=FALSE;\n"
1024 " myleaf.rec_of=TRUE;\n"
1025 " myleaf.body.node.num_of_nodes=encoded_num_of_records;\n"
1026 " myleaf.body.node.nodes=init_nodes_of_enc_tree(encoded_num_of_records);\n"
1027 " for(int a=0;a<encoded_num_of_records;a++){\n"
1028 " myleaf.body.node.nodes[a]=new RAW_enc_tree(TRUE,&myleaf,"
a38c6d4c 1029 "&(myleaf.curr_pos),a,p_td.oftype_descr->raw);\n"
1030 " encoded_length+=(*this)[a].RAW_encode(*p_td.oftype_descr,"
970ed795
EL
1031 "*myleaf.body.node.nodes[a]);\n"
1032 " }\n"
1033 " return myleaf.length=encoded_length;\n}\n\n"
a38c6d4c 1034 , name
970ed795
EL
1035 );
1036 }
1037
1038 if (xer_needed) { /* XERSTUFF encoder codegen for record-of, RT1 */
1039 def = mputstr(def,
1040 "char **collect_ns(const XERdescriptor_t& p_td, size_t& num, bool& def_ns) const;\n");
1041
1042 /* Write the body of the XER encoder/decoder functions. The declaration
1043 * is written by def_encdec() in encdec.c */
1044 src = mputprintf(src,
1045 "boolean %s::can_start(const char *name, const char *uri, "
1046 "XERdescriptor_t const& xd, unsigned int flavor) {\n"
1047 " boolean e_xer = is_exer(flavor);\n"
a38c6d4c 1048 " if ((!e_xer || !(xd.xer_bits & UNTAGGED)) && !(flavor & XER_RECOF)) return "
1049 "check_name(name, xd, e_xer) && (!e_xer || check_namespace(uri, xd));\n"
1050 " if (e_xer && (xd.oftype_descr->xer_bits & ANY_ELEMENT)) "
970ed795
EL
1051 , name
1052 );
a38c6d4c 1053 if (!force_gen_seof && sdef->nFollowers) {
970ed795
EL
1054 /* If there are optional fields following the record-of, then seeing
1055 * {any XML tag that belongs to those fields} where the record-of may be
1056 * means that the record-of is empty. */
1057 size_t f;
1058 src = mputstr(src, "{\n");
1059 for (f = 0; f < sdef->nFollowers; ++f) {
1060 src = mputprintf(src,
1061 " if (%s::can_start(name, uri, %s_xer_, flavor)) return FALSE;\n"
1062 , sdef->followers[f].type
1063 , sdef->followers[f].typegen
1064 );
1065 }
1066 src = mputstr(src,
1067 " return TRUE;\n"
1068 " }\n");
1069 }
1070 else src = mputstr(src, "return TRUE;\n");
1071
1072 src = mputprintf(src,
a38c6d4c 1073 " return %s::can_start(name, uri, *xd.oftype_descr, flavor | XER_RECOF);\n"
970ed795
EL
1074 "}\n\n"
1075 , sdef->type
970ed795
EL
1076 );
1077
1078 src = mputprintf(src,
1079 "char ** %s::collect_ns(const XERdescriptor_t& p_td, size_t& num, bool& def_ns) const {\n"
1080 " size_t num_collected;\n"
1081 " char **collected_ns = Base_Type::collect_ns(p_td, num_collected, def_ns);\n"
1082 /* The above may throw but then nothing was allocated. */
1083 " if (val_ptr) try {\n"
1084 " char **new_ns;\n"
1085 " size_t num_new;\n"
af710487 1086 " for (int i = 0; i < val_ptr->n_elements; ++i) {\n"
970ed795 1087 " bool def_ns_1 = false;"
a38c6d4c 1088 " new_ns = (*this)[i].collect_ns(*p_td.oftype_descr, num_new, def_ns_1);\n"
970ed795
EL
1089 " merge_ns(collected_ns, num_collected, new_ns, num_new);\n"
1090 " def_ns = def_ns || def_ns_1;\n" /* alas, no ||= */
1091 " }\n"
1092 " }\n"
1093 " catch (...) {\n"
1094 /* Probably a TC_Error thrown from elements[i]->collect_ns() if e.g.
1095 * encoding an unbound value. */
1096 " while (num_collected > 0) Free(collected_ns[--num_collected]);\n"
1097 " Free(collected_ns);\n"
1098 " throw;\n"
1099 " }\n"
1100 " num = num_collected;\n"
1101 " return collected_ns;\n"
1102 "}\n\n"
a38c6d4c 1103 , name);
970ed795
EL
1104
1105 src=mputprintf(src,
af710487 1106 "int %s::XER_encode(const XERdescriptor_t& p_td, TTCN_Buffer& p_buf, "
1107 "unsigned int p_flavor, int p_indent, embed_values_enc_struct_t* emb_val) const\n{\n"
970ed795
EL
1108 " if (val_ptr == 0) TTCN_error(\"Attempt to XER-encode an unbound record of\");\n" /* TODO type name */
1109 " int encoded_length=(int)p_buf.get_len();\n"
1110 " boolean e_xer = is_exer(p_flavor);\n"
1111 " boolean own_tag = !(e_xer && p_indent && ((p_td.xer_bits & (ANY_ELEMENT|ANY_ATTRIBUTES|UNTAGGED))\n"
1112 " || (p_flavor & USE_TYPE_ATTR)));\n"
1113 " boolean indenting = !is_canonical(p_flavor) && own_tag;\n"
1114 "%s" /* Factor out p_indent if not attribute */
af710487 1115 " if (val_ptr->n_elements==0) {\n" /* Empty record of */
970ed795 1116 , name
a38c6d4c 1117 , force_gen_seof ? " if (indenting && !(p_td.xer_bits & XER_ATTRIBUTE)) do_indent(p_buf, p_indent);\n"
1118 : (sdef->xerAttribute ? "" : " if (indenting) do_indent(p_buf, p_indent);\n")
970ed795 1119 );
a38c6d4c 1120 if (force_gen_seof || sdef->xerAttribute) {
1121 src=mputprintf(src,
1122 " if (e_xer%s) {\n" /* Empty attribute. */
970ed795
EL
1123 " begin_attribute(p_td, p_buf);\n"
1124 " p_buf.put_c('\\'');\n"
a38c6d4c 1125 " } else\n"
1126 , force_gen_seof ? " && (p_td.xer_bits & XER_ATTRIBUTE)" : "");
970ed795 1127 }
a38c6d4c 1128 if (force_gen_seof || !sdef->xerAttribute) {
970ed795
EL
1129 src = mputstr(src,
1130 " if (own_tag)");
1131 }
1132 src=mputprintf(src,
1133 " {\n" /* Do empty element tag */
1134 "%s"
1135 " p_buf.put_c('<');\n"
1136 " if (e_xer) write_ns_prefix(p_td, p_buf);\n"
1137 " p_buf.put_s((size_t)p_td.namelens[e_xer]-2, (const unsigned char*)p_td.names[e_xer]);\n"
1138 /* namespace declarations for the toplevel element */
1139 " if (e_xer && p_indent==0)\n"
1140 " {\n"
1141 " size_t num_collected = 0;\n"
1142 " char **collected_ns = NULL;\n"
1143 " bool def_ns = false;\n"
1144 " collected_ns = collect_ns(p_td, num_collected, def_ns);\n"
1145 " for (size_t cur_coll = 0; cur_coll < num_collected; ++cur_coll) {\n"
1146 " p_buf.put_s(strlen(collected_ns[cur_coll]), (cbyte*)collected_ns[cur_coll]);\n"
1147 " Free(collected_ns[cur_coll]);\n"
1148 " }\n"
1149 " Free(collected_ns);\n"
1150 " }\n"
1151
1152 " p_buf.put_s(2 + indenting, (const unsigned char*)\"/>\\n\");\n"
1153 " }\n"
1154 " }\n"
1155 " else {\n" /* Not empty record of. Start tag or attribute */
a38c6d4c 1156 , force_gen_seof ? " if (indenting && (p_td.xer_bits & XER_ATTRIBUTE)) do_indent(p_buf, p_indent);\n"
1157 : (sdef->xerAttribute ? " if (indenting) do_indent(p_buf, p_indent);\n" : "")
970ed795
EL
1158 );
1159 if (sdef->xerAnyAttrElem) {
1160 src = mputstr(src,
1161 " if (e_xer && (p_td.xer_bits & ANY_ATTRIBUTES)) {\n"
1162 " static const universal_char sp = { 0,0,0,' ' };\n"
1163 " static const universal_char tb = { 0,0,0,9 };\n"
1164 " size_t buf_len = p_buf.get_len(), shorter = 0;\n"
1165 " const unsigned char * const buf_data = p_buf.get_data();\n"
1166 " if (buf_data[buf_len - 1 - shorter] == '\\n') ++shorter;\n"
1167 " if (buf_data[buf_len - 1 - shorter] == '>' ) ++shorter;\n"
1168 " unsigned char saved[4];\n"
1169 " memcpy(saved, buf_data + (buf_len - shorter), shorter);\n"
1170 " p_buf.increase_length(-shorter);\n"
af710487 1171 " for (int i = 0; i < val_ptr->n_elements; ++i) {\n"
970ed795 1172 " TTCN_EncDec_ErrorContext ec_0(\"Attribute %d: \", i);\n"
af710487 1173 " if (val_ptr->value_elements[i] == NULL) {\n"
970ed795
EL
1174 " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND,\n"
1175 " \"Encoding an unbound universal charstring value.\");\n"
1176 " continue;\n"
1177 " }\n"
1178 " size_t len = val_ptr->value_elements[i]->lengthof();\n"
1179 " for (;;) {\n"
1180 " const UNIVERSAL_CHARSTRING_ELEMENT& ue = (*val_ptr->value_elements[i])[len - 1];\n"
1181 " if (sp == ue || tb == ue) --len;\n"
1182 " else break;\n"
1183 " }\n"
1184 " size_t j, sp_at = 0;\n"
1185 /* Find the "separators" in each string */
1186 " for (j = 0; j < len; j++) {\n"
1187 " UNIVERSAL_CHARSTRING_ELEMENT ue = (*val_ptr->value_elements[i])[j];\n"
1188 " if (sp_at) {\n"
1189 " if (sp == ue || tb == ue) {}\n"
1190 " else break;\n"
1191 " } else {\n"
1192 " if (sp == ue || tb == ue) sp_at = j;\n"
1193 " }\n"
1194 " } // next j\n"
1195 " size_t buf_start = p_buf.get_len();\n"
1196 /* Now write them */
1197 " if (sp_at > 0) {\n"
1198 " char * ns = mprintf(\" xmlns:b%d='\", i);\n"
1199 " size_t ns_len = mstrlen(ns);\n"
1200 " p_buf.put_s(ns_len, (const unsigned char*)ns);\n"
1201
1202 " UNIVERSAL_CHARSTRING before(sp_at, (const universal_char*)(*val_ptr->value_elements[i]));\n"
af710487 1203 " before.XER_encode(UNIVERSAL_CHARSTRING_xer_, p_buf, p_flavor | ANY_ATTRIBUTES, p_indent, 0);\n"
970ed795
EL
1204 // Ensure the namespace abides to its restrictions
1205 " if (p_td.xer_bits & (ANY_FROM | ANY_EXCEPT)) {\n"
1206 " TTCN_Buffer ns_buf;\n"
1207 " before.encode_utf8(ns_buf);\n"
1208 " CHARSTRING cs;\n"
1209 " ns_buf.get_string(cs);\n"
1210 " check_namespace_restrictions(p_td, (const char*)cs);\n"
1211 " }\n"
1212
1213 " p_buf.put_c('\\'');\n"
1214 " p_buf.put_c(' ');\n"
1215
1216 /* Keep just the "b%d" part from ns */
1217 " p_buf.put_s(ns_len - 9, (const unsigned char*)ns + 7);\n"
1218 " p_buf.put_c(':');\n"
1219 " Free(ns);\n"
1220 " }\n"
1221 " else {\n"
1222 " p_buf.put_c(' ');\n"
1223 " j = 0;\n"
1224 // Make sure the unqualified namespace is allowed
1225 " if (p_td.xer_bits & (ANY_FROM | ANY_EXCEPT)) {\n"
1226 " check_namespace_restrictions(p_td, NULL);\n"
1227 " }\n"
1228 " }\n"
1229
1230 " UNIVERSAL_CHARSTRING after(len - j, (const universal_char*)(*val_ptr->value_elements[i]) + j);\n"
af710487 1231 " after.XER_encode(UNIVERSAL_CHARSTRING_xer_, p_buf, p_flavor | ANY_ATTRIBUTES, p_indent, 0);\n"
970ed795
EL
1232 // Put this attribute in a dummy element and walk through it to check its validity
1233 " TTCN_Buffer check_buf;\n"
1234 " check_buf.put_s(2, (unsigned char*)\"<a\");\n"
1235 " check_buf.put_s(p_buf.get_len() - buf_start, p_buf.get_data() + buf_start);\n"
1236 " check_buf.put_s(2, (unsigned char*)\"/>\");"
1237 " XmlReaderWrap checker(check_buf);\n"
1238 " while (1 == checker.Read()) ;\n"
1239 " }\n"
1240
1241 " p_buf.put_s(shorter, saved);\n" /* restore the '>' and anything after */
1242 " } else {\n");
1243 }
a38c6d4c 1244 if (force_gen_seof || sdef->xerAttribute) {
1245 src=mputprintf(src,
1246 " if (e_xer%s) {\n"
970ed795 1247 " begin_attribute(p_td, p_buf);\n"
a38c6d4c 1248 " } else\n"
1249 , force_gen_seof ? " && (p_td.xer_bits & XER_ATTRIBUTE)" : "");
970ed795
EL
1250 }
1251 src=mputprintf(src,
1252 " if (own_tag) {\n"
1253 "%s"
1254 " p_buf.put_c('<');\n"
1255 " boolean write_ns = (e_xer && p_indent==0);\n"
1256 " boolean keep_newline = (indenting && !(e_xer && (p_td.xer_bits & XER_LIST)));\n"
1257 " if (e_xer) write_ns_prefix(p_td, p_buf);\n"
1258 " p_buf.put_s((size_t)p_td.namelens[e_xer]-write_ns-(write_ns || !keep_newline), "
1259 "(const unsigned char*)p_td.names[e_xer]);\n"
1260
1261 /* namespace declarations for the toplevel element */
1262 " if (e_xer && p_indent==0)\n"
1263 " {\n"
1264 " size_t num_collected = 0;\n"
1265 " char **collected_ns = NULL;\n"
1266 " bool def_ns = false;\n"
1267 " collected_ns = collect_ns(p_td, num_collected, def_ns);\n"
1268 " for (size_t cur_coll = 0; cur_coll < num_collected; ++cur_coll) {\n"
1269 " p_buf.put_s(strlen(collected_ns[cur_coll]), (cbyte*)collected_ns[cur_coll]);\n"
1270 " Free(collected_ns[cur_coll]);\n"
1271 " }\n"
1272 " Free(collected_ns);\n"
1273 " p_buf.put_s(1 + keep_newline, (cbyte*)\">\\n\");\n"
1274 " }\n"
a38c6d4c 1275 , force_gen_seof ? " if (indenting && (p_td.xer_bits & XER_ATTRIBUTE)) do_indent(p_buf, p_indent);\n"
1276 : (sdef->xerAttribute ? " if (indenting) do_indent(p_buf, p_indent);\n" : "")
970ed795
EL
1277 );
1278 if (sdef->xmlValueList) {
1279 src=mputstr(src, " if (indenting && !e_xer) do_indent(p_buf, p_indent+1);\n"); /* !e_xer or GDMO */
1280 }
1281 src=mputstr(src,
1282 " }\n"
1283 " p_flavor |= XER_RECOF | (p_td.xer_bits & XER_LIST);\n"
1284 " TTCN_EncDec_ErrorContext ec_0(\"Index \");\n"
1285 " TTCN_EncDec_ErrorContext ec_1;\n"
1286 );
a38c6d4c 1287 src=mputstr(src,
af710487 1288 " for (int i = 0; i < val_ptr->n_elements; ++i) {\n"
a38c6d4c 1289 " if (i > 0 && !own_tag && 0 != emb_val &&\n"
1290 " emb_val->embval_index < (0 != emb_val->embval_array_reg ?\n"
1291 " emb_val->embval_array_reg->size_of() : emb_val->embval_array_opt->size_of())) {\n"
1292 " if (0 != emb_val->embval_array_reg) {\n"
1293 " (*emb_val->embval_array_reg)[emb_val->embval_index].XER_encode(\n"
1294 " UNIVERSAL_CHARSTRING_xer_, p_buf, p_flavor | EMBED_VALUES, p_indent+1, 0);\n"
1295 " }\n"
1296 " else {\n"
1297 " (*emb_val->embval_array_opt)[emb_val->embval_index].XER_encode(\n"
1298 " UNIVERSAL_CHARSTRING_xer_, p_buf, p_flavor | EMBED_VALUES, p_indent+1, 0);\n"
1299 " }\n"
af710487 1300 " ++emb_val->embval_index;\n"
a38c6d4c 1301 " }\n"
1302 " ec_1.set_msg(\"%d: \", i);\n"
970ed795 1303 " if (e_xer && (p_td.xer_bits & XER_LIST) && i>0) p_buf.put_c(' ');\n"
a38c6d4c 1304 " (*this)[i].XER_encode(*p_td.oftype_descr, p_buf, p_flavor, p_indent+own_tag, emb_val);\n"
970ed795 1305 " }\n"
a38c6d4c 1306 " if (indenting && !is_exerlist(p_flavor)) {\n"
970ed795
EL
1307 );
1308 if (sdef->xmlValueList) {
1309 src=mputstr(src, " if (!e_xer) p_buf.put_c('\\n');\n"); /* !e_xer or GDMO */
1310 }
1311 src=mputstr(src,
1312 " do_indent(p_buf, p_indent);\n"
1313 " }\n");
a38c6d4c 1314 if (force_gen_seof || sdef->xerAttribute) {
1315 src=mputprintf(src,
1316 " if (e_xer%s) p_buf.put_c('\\'');\n"
1317 " else\n"
1318 , force_gen_seof ? " && (p_td.xer_bits & XER_ATTRIBUTE)" : "");
970ed795
EL
1319 }
1320 src=mputstr(src,
1321 " if (own_tag){\n"
1322 " p_buf.put_c('<');\n"
1323 " p_buf.put_c('/');\n"
1324 " if (e_xer) write_ns_prefix(p_td, p_buf);\n"
1325 " p_buf.put_s((size_t)p_td.namelens[e_xer]-!indenting, (const unsigned char*)p_td.names[e_xer]);\n"
1326 " }\n");
1327 if (sdef->xerAnyAttrElem) {
1328 src = mputstr(src, " }\n");
1329 }
1330 src=mputstr(src,
1331 " }\n" /* end if(no elements) */
1332 " return (int)p_buf.get_len() - encoded_length;\n"
1333 "}\n\n"
1334 );
1335
1336 src = mputprintf(src, /* XERSTUFF decoder codegen for record-of */
1337#ifndef NDEBUG
1338 "// written by %s in " __FILE__ " at %d\n"
1339#endif
1340 "int %s::XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& p_reader, "
af710487 1341 "unsigned int p_flavor, embed_values_dec_struct_t* emb_val)\n{\n"
970ed795
EL
1342 " boolean e_xer = is_exer(p_flavor);\n"
1343 " int xerbits = p_td.xer_bits;\n"
1344 " if (p_flavor & XER_TOPLEVEL) xerbits &= ~UNTAGGED;\n"
1345 " boolean own_tag = !(e_xer && ((xerbits & (ANY_ELEMENT|ANY_ATTRIBUTES|UNTAGGED))\n"
1346 " || (p_flavor & USE_TYPE_ATTR)));\n" /* incase the parent has USE-UNION */
1347 /* not toplevel anymore and remove the flags for USE-UNION the oftype doesn't need them */
1348 " p_flavor &= ~XER_TOPLEVEL & ~XER_LIST & ~USE_TYPE_ATTR;\n"
1349 " int rd_ok=1, xml_depth=-1;\n"
af710487 1350 " *this = NULL_VALUE;\n" /* empty but initialized array */
970ed795
EL
1351 " int type = 0;\n" /* none */
1352 " if (own_tag) for (rd_ok = p_reader.Ok(); rd_ok == 1; rd_ok = p_reader.Read()) {\n"
1353 " type = p_reader.NodeType();\n"
1354 " if (e_xer && (p_td.xer_bits & XER_ATTRIBUTE)) {\n"
1355 " if ((XML_READER_TYPE_ELEMENT == type && p_reader.MoveToFirstAttribute() == 1)\n"
1356 " || XML_READER_TYPE_ATTRIBUTE == type) {\n"
1357 " verify_name(p_reader, p_td, e_xer);\n"
1358 " break;"
1359 " }\n"
1360 " }\n"
1361 " if (e_xer && (p_td.xer_bits & XER_LIST)) {\n"
1362 " if (XML_READER_TYPE_TEXT == type) break;\n"
1363 " }\n"
1364 " else {\n"
1365 " if (XML_READER_TYPE_ELEMENT == type) {\n"
1366 " verify_name(p_reader, p_td, e_xer);\n"
1367 " xml_depth = p_reader.Depth();\n"
1368 " break;\n"
1369 " }\n"
1370 " }\n" /* endif(e_xer && list) */
1371 " }\n" /* next read */
1372 " else xml_depth = p_reader.Depth();\n"
1373 " p_flavor |= XER_RECOF;\n"
a38c6d4c 1374 " TTCN_EncDec_ErrorContext ec_0(\"Index \");\n"
1375 " TTCN_EncDec_ErrorContext ec_1;\n"
970ed795
EL
1376#ifndef NDEBUG
1377 , __FUNCTION__, __LINE__
1378#endif
1379 , name
1380 );
1381
a38c6d4c 1382 src = mputstr(src,
970ed795
EL
1383 " if (e_xer && (p_td.xer_bits & XER_LIST)) {\n" /* LIST decoding*/
1384 " char *x_val = (char*)p_reader.NewValue();\n" /* we own it */
1385 " size_t x_pos = 0;\n"
1386 " size_t x_len = strlen(x_val);\n"
1387 /* The string contains a bunch of values separated by whitespace.
1388 * Tokenize the string and create a new buffer which looks like
1389 * an XML element (<ns:name xmlns:ns='uri'>value</ns:name>),
1390 * then use that to decode the value. */
1391 " for(char * str = strtok(x_val, \" \\t\\x0A\\x0D\"); str != 0; str = strtok(x_val + x_pos, \" \\t\\x0A\\x0D\")) {\n"
1392 // Calling strtok with NULL won't work here, since the decoded element can have strtok calls aswell
1393 " x_pos += strlen(str) + 1;\n"
1394 " TTCN_Buffer buf_2;\n"
1395 " buf_2.put_c('<');\n"
a38c6d4c 1396 " write_ns_prefix(*p_td.oftype_descr, buf_2);\n"
1397 " const char * const exer_name = p_td.oftype_descr->names[1];\n"
1398 " boolean i_can_has_ns = p_td.oftype_descr->my_module != 0 && p_td.oftype_descr->ns_index != -1;\n"
970ed795 1399 /* If it has a namespace, chop off the '>' from the end */
a38c6d4c 1400 " buf_2.put_s((size_t)p_td.oftype_descr->namelens[1]-1-i_can_has_ns, (cbyte*)exer_name);\n"
970ed795 1401 " if (i_can_has_ns) {\n"
a38c6d4c 1402 " const namespace_t * const pns = p_td.oftype_descr->my_module->get_ns(p_td.oftype_descr->ns_index);\n"
970ed795
EL
1403 " buf_2.put_s(7 - (*pns->px == 0), (cbyte*)\" xmlns:\");\n"
1404 " buf_2.put_s(strlen(pns->px), (cbyte*)pns->px);\n"
1405 " buf_2.put_s(2, (cbyte*)\"='\");\n"
1406 " buf_2.put_s(strlen(pns->ns), (cbyte*)pns->ns);\n"
1407 " buf_2.put_s(2, (cbyte*)\"'>\");\n"
1408 " }\n"
1409 /* start tag completed */
1410 " buf_2.put_s(strlen(str), (cbyte*)str);\n"
1411 " buf_2.put_c('<');\n"
1412 " buf_2.put_c('/');\n"
a38c6d4c 1413 " write_ns_prefix(*p_td.oftype_descr, buf_2);\n"
1414 " buf_2.put_s((size_t)p_td.oftype_descr->namelens[1], (cbyte*)exer_name);\n"
970ed795
EL
1415 " XmlReaderWrap reader_2(buf_2);\n"
1416 " rd_ok = reader_2.Read();\n" /* Move to the start element. */
a38c6d4c 1417 " ec_1.set_msg(\"%d: \", val_ptr->n_elements);\n"
970ed795
EL
1418 /* Don't move to the #text, that's the callee's responsibility. */
1419 /* The call to the non-const operator[] creates a new element object,
1420 * then we call its XER_decode with the temporary XML reader. */
a38c6d4c 1421 " (*this)[val_ptr->n_elements].XER_decode(*p_td.oftype_descr, reader_2, p_flavor, 0);\n"
af710487 1422 " if (p_flavor & EXIT_ON_ERROR && !(*this)[val_ptr->n_elements - 1].is_bound()) {\n"
1423 " if (1 == val_ptr->n_elements) {\n"
970ed795
EL
1424 // Failed to decode even the first element
1425 " clean_up();\n"
1426 " } else {\n"
1427 // Some elements were successfully decoded -> only delete the last one
af710487 1428 " set_size(val_ptr->n_elements - 1);\n"
970ed795
EL
1429 " }\n"
1430 " xmlFree(x_val);\n"
1431 " return -1;\n"
1432 " }\n"
1433 " if (x_pos >= x_len) break;\n"
1434 " }\n"
1435 " xmlFree(x_val);\n"
1436 " if ((p_td.xer_bits & XER_ATTRIBUTE)) ;\n"
1437 /* Let the caller do AdvanceAttribute() */
1438 " else if (own_tag) {\n"
1439 " p_reader.Read();\n" /* on closing tag */
1440 " p_reader.Read();\n" /* past it */
1441 " }\n"
1442 " }\n"
970ed795
EL
1443 );
1444
1445 src = mputprintf(src,
1446 " else {\n"
1447 " if (p_flavor & PARENT_CLOSED) ;\n"
1448 /* Nothing to do, but do not advance past the parent's element */
1449 " else if (own_tag && p_reader.IsEmptyElement()) rd_ok = p_reader.Read();\n"
1450 /* It's our XML empty element: nothing to do, skip past it */
1451 " else {\n"
1452 /* Note: there is no p_reader.Read() at the end of the loop below.
1453 * Each element is supposed to consume enough to leave the next element
1454 * well-positioned. */
1455 " for (rd_ok = own_tag ? p_reader.Read() : p_reader.Ok(); rd_ok == 1; ) {\n"
1456 " type = p_reader.NodeType();\n"
1457 " if (XML_READER_TYPE_ELEMENT == type)\n"
1458 " {\n");
1459 if (sdef->xerAnyAttrElem) {
1460 src = mputprintf(src,
1461 " if (e_xer && (p_td.xer_bits & ANY_ELEMENT)) {\n"
1462 /* This is a record-of with ANY-ELEMENT applied, which is really meant
1463 * for the element type (a string), so behave like a record-of
1464 * (string with ANY-ELEMENT): call the non-const operator[]
1465 * to create a new element, then read the entire XML element into it. */
af710487 1466 " (*this)[val_ptr->n_elements] = (const char*)p_reader.ReadOuterXml();\n"
970ed795
EL
1467 /* Consume the element, then move ahead */
1468 " for (rd_ok = p_reader.Read(); rd_ok == 1 && p_reader.Depth() > xml_depth; rd_ok = p_reader.Read()) {}\n"
1469 " if (p_reader.NodeType() != XML_READER_TYPE_ELEMENT) rd_ok = p_reader.Read();\n"
1470 " } else");
1471 }
a38c6d4c 1472 src = mputstr(src,
970ed795
EL
1473 " {\n"
1474 /* An untagged record-of ends if it encounters an element with a name
1475 * that doesn't match its component */
1476 " if (!own_tag && !can_start((const char*)p_reader.LocalName(), "
a38c6d4c 1477 "(const char*)p_reader.NamespaceUri(), p_td, p_flavor)) {\n"
970ed795
EL
1478 " for (; rd_ok == 1 && p_reader.Depth() > xml_depth; rd_ok = p_reader.Read()) ;\n"
1479 " break;\n"
1480 " }\n"
a38c6d4c 1481 " ec_1.set_msg(\"%d: \", val_ptr->n_elements);\n"
970ed795 1482 /* The call to the non-const operator[] creates the element */
a38c6d4c 1483 " (*this)[val_ptr->n_elements].XER_decode(*p_td.oftype_descr, p_reader, p_flavor, emb_val);\n"
af710487 1484 " if (0 != emb_val && !own_tag && val_ptr->n_elements > 1) {\n"
1485 " ++emb_val->embval_index;\n"
1486 " }\n"
970ed795
EL
1487 " }\n"
1488 " }\n"
1489 " else if (XML_READER_TYPE_END_ELEMENT == type) {\n"
1490 " for (; p_reader.Depth() > xml_depth; rd_ok = p_reader.Read()) ;\n"
1491 " if (own_tag) {\n"
1492 " verify_end(p_reader, p_td, xml_depth, e_xer);\n"
1493 " rd_ok = p_reader.Read();\n" /* move forward one last time */
1494 " }\n"
1495 " break;\n"
1496 " }\n"
a38c6d4c 1497 " else if (XML_READER_TYPE_TEXT == type && 0 != emb_val && !own_tag && val_ptr->n_elements > 0) {\n"
af710487 1498 " UNIVERSAL_CHARSTRING emb_ustr((const char*)p_reader.Value());\n"
a38c6d4c 1499 " if (0 != emb_val->embval_array_reg) {\n"
1500 " (*emb_val->embval_array_reg)[emb_val->embval_index] = emb_ustr;\n"
1501 " }\n"
1502 " else {\n"
1503 " (*emb_val->embval_array_opt)[emb_val->embval_index] = emb_ustr;\n"
1504 " }\n"
af710487 1505 " rd_ok = p_reader.Read();\n"
a38c6d4c 1506 " }\n"
970ed795
EL
1507 " else {\n"
1508 " rd_ok = p_reader.Read();\n"
1509 " }\n"
1510 " }\n" /* next read */
1511 " }\n" /* if not empty element */
1512 " }\n" /* if not LIST */
1513 " return 1;\n"
1514 "}\n\n"
970ed795
EL
1515 );
1516 }
1517 if (json_needed) {
1518 // JSON encode, RT1
1519 src = mputprintf(src,
a38c6d4c 1520 "int %s::JSON_encode(const TTCN_Typedescriptor_t& p_td, JSON_Tokenizer& p_tok) const\n"
970ed795
EL
1521 "{\n"
1522 " if (!is_bound()) {\n"
1523 " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND,\n"
1524 " \"Encoding an unbound value of type %s.\");\n"
1525 " return -1;\n"
1526 " }\n\n"
1527 " int enc_len = p_tok.put_next_token(JSON_TOKEN_ARRAY_START, NULL);\n"
af710487 1528 " for(int i = 0; i < val_ptr->n_elements; ++i) {\n"
a38c6d4c 1529 " int ret_val = (*this)[i].JSON_encode(*p_td.oftype_descr, p_tok);\n"
970ed795
EL
1530 " if (0 > ret_val) break;\n"
1531 " enc_len += ret_val;\n"
1532 " }\n"
1533 " enc_len += p_tok.put_next_token(JSON_TOKEN_ARRAY_END, NULL);\n"
1534 " return enc_len;\n"
1535 "}\n\n"
a38c6d4c 1536 , name, dispname);
970ed795
EL
1537
1538 // JSON decode, RT1
1539 src = mputprintf(src,
a38c6d4c 1540 "int %s::JSON_decode(const TTCN_Typedescriptor_t& p_td, JSON_Tokenizer& p_tok, boolean p_silent)\n"
970ed795
EL
1541 "{\n"
1542 " json_token_t token = JSON_TOKEN_NONE;\n"
1543 " int dec_len = p_tok.get_next_token(&token, NULL, NULL);\n"
1544 " if (JSON_TOKEN_ERROR == token) {\n"
1545 " JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_BAD_TOKEN_ERROR, \"\");\n"
1546 " return JSON_ERROR_FATAL;\n"
1547 " }\n"
1548 " else if (JSON_TOKEN_ARRAY_START != token) {\n"
1549 " return JSON_ERROR_INVALID_TOKEN;\n"
1550 " }\n\n"
1551 " set_size(0);\n"
1552 " while (true) {\n"
1553 " size_t buf_pos = p_tok.get_buf_pos();\n"
1554 " %s* val = new %s;\n"
a38c6d4c 1555 " int ret_val = val->JSON_decode(*p_td.oftype_descr, p_tok, p_silent);\n"
970ed795
EL
1556 " if (JSON_ERROR_INVALID_TOKEN == ret_val) {\n"
1557 " p_tok.set_buf_pos(buf_pos);\n"
1558 " delete val;\n"
1559 " break;\n"
1560 " }\n"
1561 " else if (JSON_ERROR_FATAL == ret_val) {\n"
1562 " delete val;\n"
1563 " if (p_silent) {\n"
1564 " clean_up();\n"
1565 " }\n"
1566 " return JSON_ERROR_FATAL;\n"
1567 " }\n"
af710487 1568 " val_ptr->value_elements = (%s**)reallocate_pointers(\n"
1569 " (void**)val_ptr->value_elements, val_ptr->n_elements, val_ptr->n_elements + 1);\n"
1570 " val_ptr->value_elements[val_ptr->n_elements] = val;\n"
1571 " val_ptr->n_elements++;\n"
1572 " dec_len += ret_val;\n"
970ed795
EL
1573 " }\n\n"
1574 " dec_len += p_tok.get_next_token(&token, NULL, NULL);\n"
1575 " if (JSON_TOKEN_ARRAY_END != token) {\n"
1576 " JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_REC_OF_END_TOKEN_ERROR, \"\");\n"
1577 " if (p_silent) {\n"
1578 " clean_up();\n"
1579 " }\n"
1580 " return JSON_ERROR_FATAL;\n"
1581 " }\n\n"
1582 " return dec_len;\n"
1583 "}\n\n"
a38c6d4c 1584 , name, type, type, type);
970ed795
EL
1585 }
1586 /* end of class */
1587 def = mputstr(def, "};\n\n");
1588
1589 output->header.class_decls = mputprintf(output->header.class_decls,
1590 "class %s;\n", name);
1591 output->header.class_defs = mputstr(output->header.class_defs, def);
1592 Free(def);
1593 output->source.methods = mputstr(output->source.methods, src);
1594 Free(src);
1595 /* Copied from record.c. */
1596 output->header.function_prototypes =
1597 mputprintf(output->header.function_prototypes,
1598 "extern boolean operator==(null_type null_value, const %s& "
1599 "other_value);\n", name);
1600 output->source.function_bodies =
1601 mputprintf(output->source.function_bodies,
1602 "boolean operator==(null_type, const %s& other_value)\n"
1603 "{\n"
1604 "if (other_value.val_ptr == NULL)\n"
1605 "TTCN_error(\"The right operand of comparison is an unbound value of "
1606 "type %s.\");\n"
af710487 1607 "return other_value.val_ptr->n_elements == 0;\n"
970ed795
EL
1608 "}\n\n", name, dispname);
1609
1610 output->header.function_prototypes =
1611 mputprintf(output->header.function_prototypes,
1612 "inline boolean operator!=(null_type null_value, const %s& "
1613 "other_value) "
1614 "{ return !(null_value == other_value); }\n", name);
1615}
1616
1617/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
1618
1619void defRecordOfClassMemAllocOptimized(const struct_of_def *sdef, output_struct *output)
1620{
1621 char *def = NULL, *src = NULL;
1622 const char *name = sdef->name, *dispname = sdef->dispname;
1623 const char *type = sdef->type;
a38c6d4c 1624 boolean ber_needed = force_gen_seof || (sdef->isASN1 && enable_ber());
1625 boolean raw_needed = force_gen_seof || (sdef->hasRaw && enable_raw());
1626 boolean text_needed = force_gen_seof || (sdef->hasText && enable_text());
1627 boolean xer_needed = force_gen_seof || (sdef->hasXer && enable_xer());
1628 boolean json_needed = force_gen_seof || (sdef->hasJson && enable_json());
970ed795
EL
1629
1630 /* Class definition and private data members */
1631 def = mputprintf(def,
1632#ifndef NDEBUG
1633 "// written by %s in " __FILE__ " at %d\n"
1634#endif
1635 "class %s : public Base_Type {\n"
1636 "int n_elements;\n"
1637 "%s* value_elements;\n"
1638#ifndef NDEBUG
1639 , __FUNCTION__, __LINE__
1640#endif
1641 , name, type);
1642
1643 /* private member functions */
1644 def = mputprintf(def,
1645 "private:\n"
1646 "friend boolean operator==(null_type null_value, "
1647 "const %s& other_value);\n", name);
1648
1649 def = mputprintf(def,
1650 "void copy_value(const %s& other_value);\n", name);
1651 src = mputprintf(src,
1652 "void %s::copy_value(const %s& other_value)\n"
1653 "{\n"
1654 "if (other_value.n_elements==-1) {\n"
1655 "TTCN_error(\"Copying an unbound value of type %s.\");\n"
1656 "} else if (other_value.n_elements==0) {\n"
1657 "n_elements = 0;\n"
1658 "value_elements = NULL;\n"
1659 "} else {\n"
1660 "n_elements = other_value.n_elements;\n"
1661 "value_elements = new %s[n_elements];\n"
1662 "for (int act_elem=0; act_elem<n_elements; act_elem++) {\n"
1663 " if (other_value.value_elements[act_elem].is_bound()) {\n"
1664 " value_elements[act_elem] = other_value.value_elements[act_elem];\n"
1665 " }\n"
1666 "}\n"
1667 "}\n"
1668 "}\n\n",
1669 name, name, dispname, type);
1670
1671 if (sdef->kind == SET_OF) {
1672 /* callback function for comparison */
1673 def = mputstr(def, "static boolean compare_function("
1674 "const Base_Type *left_ptr, int left_index, "
1675 "const Base_Type *right_ptr, int right_index);\n");
1676 src = mputprintf(src, "boolean %s::compare_function("
1677 "const Base_Type *left_ptr, int left_index, "
1678 "const Base_Type *right_ptr, int right_index)\n"
1679 "{\n"
1680 "if (((const %s*)left_ptr)->n_elements==-1) "
1681 "TTCN_error(\"The left operand of comparison is an unbound value of "
1682 "type %s.\");\n"
1683 "if (((const %s*)right_ptr)->n_elements==-1) "
1684 "TTCN_error(\"The right operand of comparison is an unbound value of "
1685 "type %s.\");\n"
1686 "if (((const %s*)left_ptr)->value_elements[left_index].is_bound()){\n"
1687 "if (((const %s*)right_ptr)->value_elements[right_index].is_bound()){\n"
1688 "return ((const %s*)left_ptr)->value_elements[left_index] == "
1689 "((const %s*)right_ptr)->value_elements[right_index];\n"
1690 "} else return FALSE;\n"
1691 "} else {\n"
1692 "return !((const %s*)right_ptr)->value_elements[right_index].is_bound();\n"
1693 "}\n"
1694 "}\n\n", name, name, dispname, name, dispname, name, name, name, name, name);
1695 }
1696
1697 /* public member functions */
1698 def = mputstr(def, "\npublic:\n");
1699 def = mputprintf(def, " typedef %s of_type;\n", sdef->type);
1700
1701 /* constructors */
1702 def = mputprintf(def, "%s(): n_elements(-1), value_elements(NULL) {}\n", name);
1703
a38c6d4c 1704 def = mputprintf(def, "%s(null_type): n_elements(0), value_elements(NULL) {}\n", name);
970ed795
EL
1705
1706 /* copy constructor */
1707 def = mputprintf(def, "%s(const %s& other_value) { copy_value(other_value); }\n", name, name);
1708
1709 /* destructor */
1710 def = mputprintf(def, "~%s() { clean_up(); }\n\n", name);
1711
1712 /* clean_up function */
1713 def = mputstr(def, "void clean_up();\n");
1714 src = mputprintf(src,
1715 "void %s::clean_up()\n"
1716 "{\n"
1717 "if (n_elements!=-1) {\n"
1718 "delete[] value_elements;\n"
1719 "n_elements = -1;\n"
1720 "value_elements = NULL;\n"
1721 "}\n"
1722 "}\n\n", name);
1723
1724 /* assignment operators */
1725 def = mputprintf(def, "%s& operator=(null_type other_value);\n", name);
1726 src = mputprintf(src,
1727 "%s& %s::operator=(null_type)\n"
1728 "{\n"
1729 "clean_up();\n"
1730 "n_elements=0;\n"
1731 "value_elements=NULL;\n"
1732 "return *this;\n"
1733 "}\n\n", name, name);
1734
1735 def = mputprintf(def, "%s& operator=(const %s& other_value);\n\n",
1736 name, name);
1737 src = mputprintf(src,
1738 "%s& %s::operator=(const %s& other_value)\n"
1739 "{\n"
1740 "if (other_value.n_elements == -1) "
1741 "TTCN_error(\"Assigning an unbound value of type %s.\");\n"
1742 "if (this != &other_value) {\n"
1743 "clean_up();\n"
1744 "copy_value(other_value);\n"
1745 "}\n"
1746 "return *this;\n"
1747 "}\n\n", name, name, name, dispname);
1748
1749 /* comparison operators */
1750 def = mputstr(def, "boolean operator==(null_type other_value) const;\n");
1751 src = mputprintf(src,
1752 "boolean %s::operator==(null_type) const\n"
1753 "{\n"
1754 "if (n_elements==-1)\n"
1755 "TTCN_error(\"The left operand of comparison is an unbound value of "
1756 "type %s.\");\n"
1757 "return n_elements==0;\n"
1758 "}\n\n", name, dispname);
1759
1760 def = mputprintf(def, "boolean operator==(const %s& other_value) const;\n",
1761 name);
1762 src = mputprintf(src,
1763 "boolean %s::operator==(const %s& other_value) const\n"
1764 "{\n"
1765 "if (n_elements==-1) "
1766 "TTCN_error(\"The left operand of comparison is an unbound value of type "
1767 "%s.\");\n"
1768 "if (other_value.n_elements==-1) "
1769 "TTCN_error(\"The right operand of comparison is an unbound value of type "
1770 "%s.\");\n"
1771 "if (this==&other_value) return TRUE;\n", name, name,
1772 dispname, dispname);
1773
1774 if (sdef->kind == SET_OF) {
1775 src = mputstr(src,
1776 "return compare_set_of(this, n_elements, &other_value, "
1777 "other_value.n_elements, compare_function);\n");
1778 } else {
1779 src = mputstr(src,
1780 "if (n_elements!=other_value.n_elements) return FALSE;\n"
1781 "for (int elem_count = 0; elem_count < n_elements; elem_count++){\n"
1782 "if (value_elements[elem_count].is_bound()){\n"
1783 "if (other_value.value_elements[elem_count].is_bound()){\n"
1784 " if (value_elements[elem_count] != "
1785 "other_value.value_elements[elem_count]) return FALSE;\n"
1786 "} else return FALSE;\n"
1787 "} else {\n"
1788 "if (other_value.value_elements[elem_count].is_bound()) "
1789 "return FALSE;\n"
1790 "}\n"
1791 "}\n"
1792 "return TRUE;\n");
1793 }
1794 src = mputstr(src, "}\n\n");
1795
1796 def = mputstr(def, "inline boolean operator!=(null_type other_value) const "
1797 "{ return !(*this == other_value); }\n");
1798 def = mputprintf(def, "inline boolean operator!=(const %s& other_value) "
1799 "const { return !(*this == other_value); }\n\n", name);
1800
1801 /* indexing operators */
1802 /* Non-const operator[] is allowed to extend the record-of */
1803 def = mputprintf(def, "%s& operator[](int index_value);\n", type);
1804 src = mputprintf(src,
1805 "%s& %s::operator[](int index_value)\n"
1806 "{\n"
1807 "if (index_value < 0) TTCN_error(\"Accessing an element of type %s "
1808 "using a negative index: %%d.\", index_value);\n"
1809 "if (index_value >= n_elements) set_size(index_value + 1);\n"
1810 "return value_elements[index_value];\n"
1811 "}\n\n", type, name, dispname);
1812
1813 def = mputprintf(def, "%s& operator[](const INTEGER& index_value);\n",
1814 type);
1815 src = mputprintf(src,
1816 "%s& %s::operator[](const INTEGER& index_value)\n"
1817 "{\n"
1818 "index_value.must_bound(\"Using an unbound integer value for indexing "
1819 "a value of type %s.\");\n"
1820 "return (*this)[(int)index_value];\n"
1821 "}\n\n", type, name, dispname);
1822
1823 /* Const operator[] throws an error if over-indexing */
1824 def = mputprintf(def, "const %s& operator[](int index_value) const;\n",
1825 type);
1826 src = mputprintf(src,
1827 "const %s& %s::operator[](int index_value) const\n"
1828 "{\n"
1829 "if (n_elements==-1) TTCN_error(\"Accessing an element in an unbound "
1830 "value of type %s.\");\n"
1831 "if (index_value<0) TTCN_error(\"Accessing an element of type %s "
1832 "using a negative index: %%d.\", index_value);\n"
1833 "if (index_value>=n_elements) TTCN_error(\"Index overflow in a value "
1834 "of type %s: The index is %%d, but the value has only %%d elements.\""
1835 ", index_value, n_elements);\n"
1836 "return value_elements[index_value];\n"
1837 "}\n\n", type, name, dispname, dispname, dispname);
1838
1839 def = mputprintf(def, "const %s& operator[](const INTEGER& index_value) "
1840 "const;\n\n", type);
1841 src = mputprintf(src,
1842 "const %s& %s::operator[](const INTEGER& index_value) const\n"
1843 "{\n"
1844 "index_value.must_bound(\"Using an unbound integer value for indexing "
1845 "a value of type %s.\");\n"
1846 "return (*this)[(int)index_value];\n"
1847 "}\n\n", type, name, dispname);
1848
1849 /* rotation operators */
1850 def = mputprintf(def,
1851 "%s operator<<=(int rotate_count) const;\n"
1852 "%s operator<<=(const INTEGER& rotate_count) const;\n"
1853 "%s operator>>=(int rotate_count) const;\n"
1854 "%s operator>>=(const INTEGER& rotate_count) const;\n\n",
1855 name, name, name, name);
1856 src = mputprintf(src,
1857 "%s %s::operator<<=(int rotate_count) const\n"
1858 "{\n"
1859 "return *this >>= (-rotate_count);\n"
1860 "}\n\n"
1861 "%s %s::operator<<=(const INTEGER& rotate_count) const\n"
1862 "{\n"
1863 "rotate_count.must_bound(\""
1864 "Unbound integer operand of rotate left operator.\");\n"
1865 "return *this >>= (int)(-rotate_count);\n"
1866 "}\n\n"
1867 "%s %s::operator>>=(const INTEGER& rotate_count) const\n"
1868 "{\n"
1869 "rotate_count.must_bound(\""
1870 "Unbound integer operand of rotate right operator.\");\n"
1871 "return *this >>= (int)rotate_count;\n"
1872 "}\n\n"
1873 "%s %s::operator>>=(int rotate_count) const\n"
1874 "{\n"
1875 "if (n_elements==-1) TTCN_error(\"Performing rotation operation on an "
1876 "unbound value of type %s.\");\n"
1877 "if (n_elements==0) return *this;\n"
1878 "int rc;\n"
1879 "if (rotate_count>=0) rc = rotate_count %% n_elements;\n"
1880 "else rc = n_elements - ((-rotate_count) %% n_elements);\n"
1881 "if (rc == 0) return *this;\n"
1882 "%s ret_val;\n"
1883 "ret_val.set_size(n_elements);\n"
1884 "for (int i=0; i<n_elements; i++) {\n"
1885 "if (value_elements[i].is_bound()) "
1886 "ret_val.value_elements[(i+rc)%%n_elements] = value_elements[i];\n"
1887 "}\n"
1888 "return ret_val;\n"
1889 "}\n\n",
1890 name, name, name, name, name, name, name, name, dispname, name);
1891
1892 /* concatenation */
1893 def = mputprintf(def,
1894 "%s operator+(const %s& other_value) const;\n\n", name, name);
1895 src = mputprintf(src,
1896 "%s %s::operator+(const %s& other_value) const\n"
1897 "{\n"
1898 "if (n_elements==-1 || other_value.n_elements==-1) "
1899 "TTCN_error(\"Unbound operand of %s concatenation.\");\n"
1900 "if (n_elements==0) return other_value;\n"
1901 "if (other_value.n_elements==0) return *this;\n"
1902 "%s ret_val;\n"
1903 "ret_val.set_size(n_elements+other_value.n_elements);\n"
1904 "for (int i=0; i<n_elements; i++) {\n"
1905 "if (value_elements[i].is_bound()) "
1906 "ret_val.value_elements[i] = value_elements[i];\n"
1907 "}\n"
1908 "for (int i=0; i<other_value.n_elements; i++) {\n"
1909 "if (other_value.value_elements[i].is_bound()) "
1910 "ret_val.value_elements[i+n_elements] = other_value.value_elements[i];\n"
1911 "}\n"
1912 "return ret_val;\n"
1913 "}\n\n", name, name, name, dispname, name);
1914
1915 /* substr() */
1916 def = mputprintf(def,
1917 "%s substr(int index, int returncount) const;\n\n", name);
1918 src = mputprintf(src,
1919 "%s %s::substr(int index, int returncount) const\n"
1920 "{\n"
1921 "if (n_elements==-1) TTCN_error(\"The first argument of substr() is an "
1922 "unbound value of type %s.\");\n"
1923 "check_substr_arguments(n_elements, index, returncount, \"%s\",\"element\");\n"
1924 "%s ret_val;\n"
1925 "ret_val.set_size(returncount);\n"
1926 "for (int i=0; i<returncount; i++) {\n"
1927 "if (value_elements[i+index].is_bound()) "
1928 "ret_val.value_elements[i] = value_elements[i+index];\n"
1929 "}\n"
1930 "return ret_val;\n"
1931 "}\n\n", name, name, dispname, dispname, name);
1932
1933 /* replace() */
1934 def = mputprintf(def,
1935 "%s replace(int index, int len, const %s& repl) const;\n\n", name, name);
1936 src = mputprintf(src,
1937 "%s %s::replace(int index, int len, const %s& repl) const\n"
1938 "{\n"
1939 "if (n_elements==-1) TTCN_error(\"The first argument of replace() is an "
1940 "unbound value of type %s.\");\n"
1941 "if (repl.n_elements==-1) TTCN_error(\"The fourth argument of replace() "
1942 "is an unbound value of type %s.\");\n"
1943 "check_replace_arguments(n_elements, index, len, \"%s\",\"element\");\n"
1944 "%s ret_val;\n"
1945 "ret_val.set_size(n_elements + repl.n_elements - len);\n"
1946 "for (int i = 0; i < index; i++) {\n"
1947 "if (value_elements[i].is_bound()) "
1948 "ret_val.value_elements[i] = value_elements[i];\n"
1949 "}\n"
1950 "for (int i = 0; i < repl.n_elements; i++) {\n"
1951 "if (repl.value_elements[i].is_bound()) "
1952 "ret_val.value_elements[i+index] = repl.value_elements[i];\n"
1953 "}\n"
1954 "for (int i = 0; i < n_elements - index - len; i++) {\n"
1955 "if (value_elements[index+i+len].is_bound()) "
1956 "ret_val.value_elements[index+i+repl.n_elements] = value_elements[index+i+len];\n"
1957 "}\n"
1958 "return ret_val;\n"
1959 "}\n\n", name, name, name, dispname, dispname, dispname, name);
1960 def = mputprintf(def,
1961 "%s replace(int index, int len, const %s_template& repl) const;\n\n",
1962 name, name);
1963 src = mputprintf(src,
1964 "%s %s::replace(int index, int len, const %s_template& repl) const\n"
1965 "{\n"
1966 "if (!repl.is_value()) TTCN_error(\"The fourth argument of function "
1967 "replace() is a template with non-specific value.\");\n"
1968 "return replace(index, len, repl.valueof());\n"
1969 "}\n\n", name, name, name);
1970
1971 /* set_size function */
1972 def = mputstr(def, "void set_size(int new_size);\n");
1973 src = mputprintf(src, "void %s::set_size(int new_size)\n"
1974 "{\n"
1975 "if (new_size<0) TTCN_error(\"Internal error: Setting a negative size for "
1976 "a value of type %s.\");\n"
1977 "if (new_size==n_elements) return;\n"
1978 "if (new_size==0) {\n"
1979 " clean_up();\n"
1980 " n_elements = 0;\n"
1981 " value_elements = NULL;\n"
1982 " return;\n"
1983 "}\n"
1984 "%s* new_elem_v = new %s[new_size];\n"
1985 "for (int act_elem = 0; act_elem<n_elements; act_elem++) {\n"
1986 " if (act_elem>=new_size) break;\n"
1987 " if (value_elements[act_elem].is_bound()) new_elem_v[act_elem] = value_elements[act_elem];\n"
1988 "}\n"
1989 "clean_up();\n"
1990 "#ifdef TITAN_MEMORY_DEBUG_SET_RECORD_OF\n"
1991 "if((n_elements/1000)!=(new_size/1000)) "
1992 "TTCN_warning(\"New size of type %s: %%d\",new_size);\n"
1993 "#endif\n"
1994 "n_elements = new_size;\n"
1995 "value_elements = new_elem_v;\n"
1996 "}\n\n", name, dispname, type, type, dispname);
1997
1998 /* is_bound function */
1999 def = mputstr(def,
2000 "inline boolean is_bound() const {return n_elements!=-1; }\n");
2001
2002 /* is_present function */
2003 def = mputstr(def,
2004 "inline boolean is_present() const { return is_bound(); }\n");
2005
2006 /* is_value function */
2007 def = mputstr(def,
2008 "boolean is_value() const;\n");
2009 src = mputprintf(src,
2010 "boolean %s::is_value() const\n"
2011 "{\n"
2012 "if (n_elements==-1) return FALSE;\n"
2013 "for (int i = 0; i < n_elements; ++i) {\n"
2014 " if (!value_elements[i].is_value()) return FALSE;\n"
2015 "}\n"
2016 "return TRUE;\n"
2017 "}\n\n", name);
2018
2019 /* sizeof operation */
2020 def = mputstr(def,
2021 "int size_of() const;\n"
2022 "int n_elem() const { return size_of(); }\n");
2023 src = mputprintf(src,
2024 "int %s::size_of() const\n"
2025 "{\n"
2026 "if (n_elements==-1) TTCN_error(\"Performing sizeof operation on an "
2027 "unbound value of type %s.\");\n"
2028 "return n_elements;\n"
2029 "}\n\n", name, dispname);
2030
2031 /* lengthof operation */
2032 def = mputstr(def, "int lengthof() const;\n");
2033 src = mputprintf(src,
2034 "int %s::lengthof() const\n"
2035 "{\n"
2036 "if (n_elements==-1) TTCN_error(\"Performing lengthof operation on an "
2037 "unbound value of type %s.\");\n"
2038 "for (int my_length=n_elements; my_length>0; my_length--) "
2039 "if (value_elements[my_length-1].is_bound()) return my_length;\n"
2040 "return 0;\n"
2041 "}\n\n", name, dispname);
2042
2043 /* log function */
2044 def = mputstr(def, "void log() const;\n");
2045 src = mputprintf(src,
2046 "void %s::log() const\n"
2047 "{\n"
2048 "if (n_elements==-1) {;\n"
2049 "TTCN_Logger::log_event_unbound();\n"
2050 "return;\n"
2051 "}\n"
2052 "switch (n_elements) {\n"
2053 "case 0:\n"
2054 "TTCN_Logger::log_event_str(\"{ }\");\n"
2055 "break;\n"
2056 "default:\n"
2057 "TTCN_Logger::log_event_str(\"{ \");\n"
2058 "for (int elem_count = 0; elem_count < n_elements; elem_count++) {\n"
2059 "if (elem_count > 0) TTCN_Logger::log_event_str(\", \");\n"
2060 "value_elements[elem_count].log();\n"
2061 "}\n"
2062 "TTCN_Logger::log_event_str(\" }\");\n"
2063 "}\n"
2064 "}\n\n", name);
2065
2066 /* set_param function */ /* this is an exact copy of the previous one in this source file, if we didn't forget... */
2067 def = mputstr(def, "void set_param(Module_Param& param);\n");
2068 src = mputprintf(src,
2069 "void %s::set_param(Module_Param& param)\n"
2070 "{\n"
2071 " if (dynamic_cast<Module_Param_Name*>(param.get_id()) != NULL &&\n"
2072 " param.get_id()->next_name()) {\n"
2073 // Haven't reached the end of the module parameter name
2074 // => the name refers to one of the elements, not to the whole record of
2075 " char* param_field = param.get_id()->get_current_name();\n"
2076 " if (param_field[0] < '0' || param_field[0] > '9') {\n"
2077 " param.error(\"Unexpected record field name in module parameter, expected a valid\"\n"
2078 " \" index for %s type `%s'\");\n"
2079 " }\n"
2080 " int param_index = -1;\n"
2081 " sscanf(param_field, \"%%d\", &param_index);\n"
2082 " (*this)[param_index].set_param(param);\n"
2083 " return;\n"
2084 " }\n"
2085 " param.basic_check(Module_Param::BC_VALUE|Module_Param::BC_LIST, \"%s value\");\n"
2086 " switch (param.get_operation_type()) {\n"
2087 " case Module_Param::OT_ASSIGN:\n"
2088 " if (param.get_type()==Module_Param::MP_Value_List && param.get_size()==0) {\n"
2089 " *this = NULL_VALUE;\n"
2090 " return;\n"
2091 " }\n"
2092 " switch (param.get_type()) {\n"
2093 " case Module_Param::MP_Value_List:\n"
2094 " set_size(param.get_size());\n"
2095 " for (size_t i=0; i<param.get_size(); ++i) {\n"
2096 " Module_Param* const curr = param.get_elem(i);\n"
2097 " if (curr->get_type()!=Module_Param::MP_NotUsed) {\n"
2098 " (*this)[i].set_param(*curr);\n"
2099 " }\n"
2100 " }\n"
2101 " break;\n"
2102 " case Module_Param::MP_Indexed_List:\n"
2103 " for (size_t i=0; i<param.get_size(); ++i) {\n"
2104 " Module_Param* const curr = param.get_elem(i);\n"
2105 " (*this)[curr->get_id()->get_index()].set_param(*curr);\n"
2106 " }\n"
2107 " break;\n"
2108 " default:\n"
2109 " param.type_error(\"%s value\", \"%s\");\n"
2110 " }\n"
2111 " break;\n"
2112 " case Module_Param::OT_CONCAT:\n"
2113 " switch (param.get_type()) {\n"
2114 " case Module_Param::MP_Value_List: {\n"
2115 " if (!is_bound()) *this = NULL_VALUE;\n"
2116 " int start_idx = lengthof();\n"
2117 " for (size_t i=0; i<param.get_size(); ++i) {\n"
2118 " Module_Param* const curr = param.get_elem(i);\n"
2119 " if ((curr->get_type()!=Module_Param::MP_NotUsed)) {\n"
2120 " (*this)[start_idx+(int)i].set_param(*curr);\n"
2121 " }\n"
2122 " }\n"
2123 " } break;\n"
2124 " case Module_Param::MP_Indexed_List:\n"
2125 " param.error(\"Cannot concatenate an indexed value list\");\n"
2126 " break;\n"
2127 " default:\n"
2128 " param.type_error(\"%s value\", \"%s\");\n"
2129 " }\n"
2130 " break;\n"
2131 " default:\n"
2132 " TTCN_error(\"Internal error: Unknown operation type.\");\n"
2133 " }\n"
2134 "}\n", name, sdef->kind == RECORD_OF ? "record of" : "set of", dispname,
2135 sdef->kind == RECORD_OF ? "record of" : "set of",
2136 sdef->kind == RECORD_OF ? "record of" : "set of", dispname,
2137 sdef->kind == RECORD_OF ? "record of" : "set of", dispname);
2138
2139 /* encoding / decoding functions */
2140 def = mputstr(def, "void encode_text(Text_Buf& text_buf) const;\n");
2141 src = mputprintf(src,
2142 "void %s::encode_text(Text_Buf& text_buf) const\n"
2143 "{\n"
2144 "if (n_elements==-1) "
2145 "TTCN_error(\"Text encoder: Encoding an unbound value of type %s.\");\n"
2146 "text_buf.push_int(n_elements);\n"
2147 "for (int elem_count = 0; elem_count < n_elements; elem_count++)\n"
2148 "value_elements[elem_count].encode_text(text_buf);\n"
2149 "}\n\n", name, dispname);
2150
2151 def = mputstr(def, "void decode_text(Text_Buf& text_buf);\n");
2152 src = mputprintf(src,
2153 "void %s::decode_text(Text_Buf& text_buf)\n"
2154 "{\n"
2155 "clean_up();\n"
2156 "n_elements = text_buf.pull_int().get_val();\n"
2157 "if (n_elements < 0) TTCN_error(\"Text decoder: Negative size "
2158 "was received for a value of type %s.\");\n"
2159 "if (n_elements==0) {\n"
2160 " value_elements = NULL;\n"
2161 " return;\n"
2162 "}\n"
2163 "value_elements = new %s[n_elements];\n"
2164 "for (int elem_count = 0; elem_count < n_elements; elem_count++) {\n"
2165 " value_elements[elem_count].decode_text(text_buf);\n"
2166 "}\n"
2167 "}\n\n", name, dispname, type);
2168
2169 if(ber_needed || raw_needed || text_needed || xer_needed || json_needed)
2170 def_encdec(name, &def, &src, ber_needed, raw_needed, text_needed,
2171 xer_needed, json_needed, FALSE);
2172
2173 if (text_needed) {
2174 src=mputprintf(src,
2175 "int %s::TEXT_encode(const TTCN_Typedescriptor_t& p_td,"
2176 " TTCN_Buffer& p_buf) const{\n"
2177 " int encoded_length=0;\n"
2178 " if(p_td.text->begin_encode){\n"
2179 " p_buf.put_cs(*p_td.text->begin_encode);\n"
2180 " encoded_length+=p_td.text->begin_encode->lengthof();\n"
2181 " }\n"
2182 " if(n_elements==-1) {\n"
2183 " TTCN_EncDec_ErrorContext::error\n"
2184 " (TTCN_EncDec::ET_UNBOUND, \"Encoding an unbound value.\");\n"
2185 " if(p_td.text->end_encode){\n"
2186 " p_buf.put_cs(*p_td.text->end_encode);\n"
2187 " encoded_length+=p_td.text->end_encode->lengthof();\n"
2188 " }\n"
2189 " return encoded_length;\n"
2190 " }\n"
2191 " for(int a=0;a<n_elements;a++){\n"
2192 " if(a!=0 && p_td.text->separator_encode){\n"
2193 " p_buf.put_cs(*p_td.text->separator_encode);\n"
2194 " encoded_length+=p_td.text->separator_encode->lengthof();\n"
2195 " }\n"
a38c6d4c 2196 " encoded_length+=value_elements[a].TEXT_encode(*p_td.oftype_descr,p_buf);\n"
970ed795
EL
2197 " }\n"
2198 " if(p_td.text->end_encode){\n"
2199 " p_buf.put_cs(*p_td.text->end_encode);\n"
2200 " encoded_length+=p_td.text->end_encode->lengthof();\n"
2201 " }\n"
2202 " return encoded_length;\n"
2203 "}\n"
a38c6d4c 2204 ,name
970ed795
EL
2205 );
2206 src = mputprintf(src,
2207 "int %s::TEXT_decode(const TTCN_Typedescriptor_t& p_td,"
2208 " TTCN_Buffer& p_buf, Limit_Token_List& limit, boolean no_err"
2209 ", boolean first_call){\n"
2210 " int decoded_length=0;\n"
2211 " size_t pos=p_buf.get_pos();\n"
2212 " boolean sep_found=FALSE;\n"
2213 " int sep_length=0;\n"
2214 " int ml=0;\n"
2215 " if(p_td.text->begin_decode){\n"
2216 " int tl;\n"
2217 " if((tl=p_td.text->begin_decode->match_begin(p_buf))<0){\n"
2218 " if(no_err)return -1;\n"
2219 " TTCN_EncDec_ErrorContext::error\n"
2220 " (TTCN_EncDec::ET_TOKEN_ERR, \"The specified token '%%s'"
2221 " not found for '%%s': \",(const char*)*(p_td.text->begin_decode)"
2222 ", p_td.name);\n"
2223 " return 0;\n"
2224 " }\n"
2225 " decoded_length+=tl;\n"
2226 " p_buf.increase_pos(tl);\n"
2227 " }\n"
2228 " if(p_td.text->end_decode){\n"
2229 " limit.add_token(p_td.text->end_decode);\n"
2230 " ml++;\n"
2231 " }\n"
2232 " if(p_td.text->separator_decode){\n"
2233 " limit.add_token(p_td.text->separator_decode);\n"
2234 " ml++;\n"
2235 " }\n"
2236 " if(first_call) {\n"
2237 " set_size(0);\n"
2238 " }\n"
2239 " int more=n_elements;\n"
2240 " while(TRUE){\n"
2241 " %s val;\n"
2242 " pos=p_buf.get_pos();\n"
a38c6d4c 2243 " int len=val.TEXT_decode(*p_td.oftype_descr,p_buf,limit,TRUE);\n"
970ed795
EL
2244 " if(len==-1 || (len==0 && !limit.has_token())){\n"
2245 " p_buf.set_pos(pos);\n"
2246 " if(sep_found){\n"
2247 " p_buf.set_pos(p_buf.get_pos()-sep_length);\n"
2248 " decoded_length-=sep_length;\n"
2249 " }\n"
2250 " break;\n"
2251 " }\n"
2252 " sep_found=FALSE;\n"
2253 " set_size(n_elements+1);\n"
2254 " value_elements[n_elements-1]=val;\n"
2255 " decoded_length+=len;\n"
2256 " if(p_td.text->separator_decode){\n"
2257 " int tl;\n"
2258 " if((tl=p_td.text->separator_decode->match_begin(p_buf))<0){\n"
2259 " break;\n"
2260 " }\n"
2261 " decoded_length+=tl;\n"
2262 " p_buf.increase_pos(tl);\n"
2263 " sep_length=tl;\n"
2264 " sep_found=TRUE;\n"
2265 " } else if(p_td.text->end_decode){\n"
2266 " int tl;\n"
2267 " if((tl=p_td.text->end_decode->match_begin(p_buf))!=-1){\n"
2268 " decoded_length+=tl;\n"
2269 " p_buf.increase_pos(tl);\n"
2270 " limit.remove_tokens(ml);\n"
2271 " return decoded_length;\n"
2272 " }\n"
2273 " } else if(limit.has_token(ml)){\n"
2274 " int tl;\n"
2275 " if((tl=limit.match(p_buf,ml))==0){\n"
2276 " sep_found=FALSE;\n"
2277 " break;\n"
2278 " }\n"
2279 " }\n"
2280 " }\n"
a38c6d4c 2281 ,name,type
970ed795
EL
2282 );
2283 src = mputstr(src,
2284 " limit.remove_tokens(ml);\n"
2285 " if(p_td.text->end_decode){\n"
2286 " int tl;\n"
2287 " if((tl=p_td.text->end_decode->match_begin(p_buf))<0){\n"
2288 " if(no_err){"
2289 " if(!first_call){\n"
2290 " set_size(more);\n"
2291 " }\n"
2292 " return -1;\n"
2293 " }\n"
2294 " TTCN_EncDec_ErrorContext::error"
2295 "(TTCN_EncDec::ET_TOKEN_ERR, \"The specified token '%s'"
2296 " not found for '%s': \",(const char*)*(p_td.text->end_decode)"
2297 ",p_td.name);\n"
2298 " return decoded_length;\n"
2299 " }\n"
2300 " decoded_length+=tl;\n"
2301 " p_buf.increase_pos(tl);\n"
2302 " }\n"
2303 " if(n_elements==0){\n"
2304 " if(p_td.text->end_decode || p_td.text->begin_decode) n_elements=0;\n"
2305 " else {\n"
2306 " if(no_err)return -1;\n"
2307 " TTCN_EncDec_ErrorContext::error"
2308 "(TTCN_EncDec::ET_TOKEN_ERR, \"No record/set of member found.\");\n"
2309 " return decoded_length;\n"
2310 " }\n"
2311 " }\n"
2312 " if(!first_call && more==n_elements && "
2313 "!(p_td.text->end_decode || p_td.text->begin_decode)) return -1;\n"
2314 " return decoded_length;\n"
2315 "}\n"
2316 );
2317 }
2318
2319 /* BER functions */
2320 if(ber_needed) {
2321 /* BER_encode_TLV() */
2322 src=mputprintf
2323 (src,
2324 "ASN_BER_TLV_t* %s::BER_encode_TLV(const TTCN_Typedescriptor_t&"
2325 " p_td, unsigned p_coding) const\n"
2326 "{\n"
2327 " BER_chk_descr(p_td);\n"
2328 " ASN_BER_TLV_t *new_tlv=BER_encode_chk_bound(is_bound());\n"
2329 " if(!new_tlv) {\n"
2330 " new_tlv=ASN_BER_TLV_t::construct(NULL);\n"
2331 " TTCN_EncDec_ErrorContext ec;\n"
2332 " for(int elem_i=0; elem_i<n_elements; elem_i++) {\n"
2333 " ec.set_msg(\"Component #%%d: \", elem_i);\n"
2334 " new_tlv->add_TLV(value_elements[elem_i].BER_encode_TLV"
a38c6d4c 2335 "(*p_td.oftype_descr, p_coding));\n"
970ed795
EL
2336 " }\n"
2337 "%s"
2338 " }\n"
2339 " new_tlv=ASN_BER_V2TLV(new_tlv, p_td, p_coding);\n"
2340 " return new_tlv;\n"
2341 "}\n"
2342 "\n"
2343 /* BER_decode_TLV() */
2344 "boolean %s::BER_decode_TLV(const TTCN_Typedescriptor_t& p_td,"
2345 " const ASN_BER_TLV_t& p_tlv, unsigned L_form)\n"
2346 "{\n"
2347 " BER_chk_descr(p_td);\n"
2348 " ASN_BER_TLV_t stripped_tlv;\n"
2349 " BER_decode_strip_tags(*p_td.ber, p_tlv, L_form, stripped_tlv);\n"
2350 " TTCN_EncDec_ErrorContext ec_0(\"While decoding '%%s' type: \","
2351 " p_td.name);\n"
2352 " stripped_tlv.chk_constructed_flag(TRUE);\n"
2353 " set_size(0);\n"
2354 " size_t V_pos=0;\n"
2355 " ASN_BER_TLV_t tmp_tlv;\n"
2356 " TTCN_EncDec_ErrorContext ec_1(\"Component #\");\n"
2357 " TTCN_EncDec_ErrorContext ec_2(\"0: \");\n"
2358 " while(BER_decode_constdTLV_next(stripped_tlv, V_pos, L_form, "
2359 "tmp_tlv)) {\n"
2360 " set_size(n_elements+1);\n"
a38c6d4c 2361 " value_elements[n_elements-1].BER_decode_TLV(*p_td.oftype_descr, tmp_tlv, "
970ed795
EL
2362 "L_form);\n"
2363 " ec_2.set_msg(\"%%d: \", n_elements);\n"
2364 " }\n"
2365 " return TRUE;\n"
2366 "}\n"
2367 "\n"
a38c6d4c 2368 , name
970ed795 2369 , sdef->kind==SET_OF?" new_tlv->sort_tlvs();\n":""
a38c6d4c 2370 , name
970ed795
EL
2371 );
2372
2373 if(sdef->has_opentypes) {
2374 /* BER_decode_opentypes() */
2375 def=mputstr
2376 (def,
2377 "void BER_decode_opentypes(TTCN_Type_list& p_typelist,"
2378 " unsigned L_form);\n");
2379 src=mputprintf
2380 (src,
2381 "void %s::BER_decode_opentypes(TTCN_Type_list& p_typelist,"
2382 " unsigned L_form)\n"
2383 "{\n"
2384 " p_typelist.push(this);\n"
2385 " TTCN_EncDec_ErrorContext ec_0(\"Component #\");\n"
2386 " TTCN_EncDec_ErrorContext ec_1;\n"
2387 " for(int elem_i=0; elem_i<n_elements; elem_i++) {\n"
2388 " ec_1.set_msg(\"%%d: \", elem_i);\n"
2389 " value_elements[elem_i].BER_decode_opentypes(p_typelist,"
2390 " L_form);\n"
2391 " }\n"
2392 " p_typelist.pop();\n"
2393 "}\n"
2394 "\n"
2395 , name
2396 );
2397 }
2398 }
2399
2400 if(raw_needed){
2401 src=mputprintf(src,
2402 "int %s::RAW_decode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf, "
2403 "int limit, raw_order_t top_bit_ord, boolean /*no_err*/, int sel_field"
2404 ", boolean first_call){\n"
2405 " int prepaddlength=p_buf.increase_pos_padd(p_td.raw->prepadding);\n"
2406 " limit-=prepaddlength;\n"
2407 " int decoded_length=0;\n"
2408 " int decoded_field_length=0;\n"
2409 " size_t start_of_field=0;\n"
2410 " if (first_call) set_size(0);\n"
2411 " int start_field=n_elements;\n"
2412 " if(p_td.raw->fieldlength || sel_field!=-1){\n"
2413 " int a=0;\n"
2414 " if(sel_field==-1) sel_field=p_td.raw->fieldlength;\n"
2415 " for(a=0;a<sel_field;a++){\n"
a38c6d4c 2416 " decoded_field_length=(*this)[a+start_field].RAW_decode(*p_td.oftype_descr,"
970ed795
EL
2417 "p_buf,limit,top_bit_ord,TRUE);\n"
2418 " if(decoded_field_length < 0) return decoded_field_length;\n"
2419 " decoded_length+=decoded_field_length;\n"
2420 " limit-=decoded_field_length;\n"
2421 " }\n"
2422 " if(a==0) n_elements=0;\n"
2423 " } else {\n"
2424 " int a=start_field;\n"
2425 " if(limit==0){\n"
2426 " if(!first_call) return -1;\n"
2427 " n_elements=0;\n"
2428 " return decoded_length+p_buf.increase_pos_padd(p_td.raw->padding)"
2429 "+prepaddlength;\n"
2430 " }\n"
2431 " while(limit>0){\n"
2432 " start_of_field=p_buf.get_pos_bit();\n"
a38c6d4c 2433 " decoded_field_length=(*this)[a].RAW_decode(*p_td.oftype_descr,p_buf,limit,"
970ed795
EL
2434 "top_bit_ord,TRUE);\n"
2435 " if(decoded_field_length < 0){\n"
2436 /*" delete &(*this)[a];\n"*/
2437 " n_elements--;\n"
2438 " p_buf.set_pos_bit(start_of_field);\n"
2439 " if(a>start_field){\n"
2440 " return decoded_length+p_buf.increase_pos_padd(p_td.raw->padding)"
2441 "+prepaddlength;\n"
2442 " } else return -1;\n"
2443 " }\n"
2444 " decoded_length+=decoded_field_length;\n"
2445 " limit-=decoded_field_length;\n"
2446 " a++;\n"
a38c6d4c 2447 ,name
970ed795
EL
2448 );
2449 if(sdef->raw.extension_bit!=XDEFNO && sdef->raw.extension_bit!=XDEFDEFAULT){
2450 src=mputprintf(src,
2451 " if (%sp_buf.get_last_bit())\n"
2452 " return decoded_length+p_buf.increase_pos_padd(p_td.raw->padding)"
2453 "+prepaddlength;\n", sdef->raw.extension_bit == XDEFYES ? "" : "!");
2454 }
2455 src=mputprintf(src,
2456 " }\n"
2457 " }\n"
2458 " return decoded_length+p_buf.increase_pos_padd(p_td.raw->padding)"
2459 "+prepaddlength;\n"
2460 "}\n\n"
2461 "int %s::RAW_encode(const TTCN_Typedescriptor_t& p_td,"
2462 "RAW_enc_tree& myleaf) const{\n"
2463 " int encoded_length=0;\n"
2464 " int encoded_num_of_records=p_td.raw->fieldlength?"
2465 "smaller(n_elements, p_td.raw->fieldlength):n_elements;\n"
2466 " myleaf.isleaf=FALSE;\n"
2467 " myleaf.rec_of=TRUE;\n"
2468 " myleaf.body.node.num_of_nodes=encoded_num_of_records;\n"
2469 " myleaf.body.node.nodes=init_nodes_of_enc_tree(encoded_num_of_records);\n"
2470 " for(int a=0;a<encoded_num_of_records;a++){\n"
2471 " myleaf.body.node.nodes[a]=new RAW_enc_tree(TRUE,&myleaf,"
a38c6d4c 2472 "&(myleaf.curr_pos),a,p_td.oftype_descr->raw);\n"
2473 " encoded_length+=(*this)[a].RAW_encode(*p_td.oftype_descr,"
970ed795
EL
2474 "*myleaf.body.node.nodes[a]);\n"
2475 " }\n"
2476 " return myleaf.length=encoded_length;\n}\n\n"
a38c6d4c 2477 , name
970ed795
EL
2478 );
2479 }
2480
2481 if (xer_needed) { /* XERSTUFF encoder codegen for record-of, RT1 */
2482 def = mputstr(def,
2483 "char **collect_ns(const XERdescriptor_t& p_td, size_t& num, bool& def_ns) const;\n");
2484
2485 /* Write the body of the XER encoder/decoder functions. The declaration
2486 * is written by def_encdec() in encdec.c */
2487 src = mputprintf(src,
2488 "boolean %s::can_start(const char *name, const char *uri, "
2489 "XERdescriptor_t const& xd, unsigned int flavor) {\n"
2490 " boolean e_xer = is_exer(flavor);\n"
a38c6d4c 2491 " if ((!e_xer || !(xd.xer_bits & UNTAGGED)) && !(flavor & XER_RECOF)) return "
2492 "check_name(name, xd, e_xer) && (!e_xer || check_namespace(uri, xd));\n"
2493 " if (e_xer && (xd.oftype_descr->xer_bits & ANY_ELEMENT)) "
970ed795
EL
2494 , name
2495 );
a38c6d4c 2496 if (!force_gen_seof && sdef->nFollowers) {
970ed795
EL
2497 /* If there are optional fields following the record-of, then seeing
2498 * {any XML tag that belongs to those fields} where the record-of may be
2499 * means that the record-of is empty. */
2500 size_t f;
2501 src = mputstr(src, "{\n");
2502 for (f = 0; f < sdef->nFollowers; ++f) {
2503 src = mputprintf(src,
2504 " if (%s::can_start(name, uri, %s_xer_, flavor)) return FALSE;\n"
2505 , sdef->followers[f].type
2506 , sdef->followers[f].typegen
2507 );
2508 }
2509 src = mputstr(src,
2510 " return TRUE;\n"
2511 " }\n");
2512 }
2513 else src = mputstr(src, "return TRUE;\n");
2514
2515 src = mputprintf(src,
a38c6d4c 2516 " return %s::can_start(name, uri, *xd.oftype_descr, flavor | XER_RECOF);\n"
970ed795
EL
2517 "}\n\n"
2518 , sdef->type
970ed795
EL
2519 );
2520
2521 src = mputprintf(src,
2522 "char ** %s::collect_ns(const XERdescriptor_t& p_td, size_t& num, bool& def_ns) const {\n"
2523 " size_t num_collected;\n"
2524 " char **collected_ns = Base_Type::collect_ns(p_td, num_collected, def_ns);\n"
2525 /* The above may throw but then nothing was allocated. */
2526 " if (n_elements!=-1) try {\n"
2527 " char **new_ns;\n"
2528 " size_t num_new;\n"
2529 " for (int i = 0; i < n_elements; ++i) {\n"
2530 " bool def_ns_1 = false;"
a38c6d4c 2531 " new_ns = value_elements[i].collect_ns(*p_td.oftype_descr, num_new, def_ns_1);\n"
970ed795
EL
2532 " merge_ns(collected_ns, num_collected, new_ns, num_new);\n"
2533 " def_ns = def_ns || def_ns_1;\n" /* alas, no ||= */
2534 " }\n"
2535 " }\n"
2536 " catch (...) {\n"
2537 /* Probably a TC_Error thrown from elements[i]->collect_ns() if e.g.
2538 * encoding an unbound value. */
2539 " while (num_collected > 0) Free(collected_ns[--num_collected]);\n"
2540 " Free(collected_ns);\n"
2541 " throw;\n"
2542 " }\n"
2543 " num = num_collected;\n"
2544 " return collected_ns;\n"
2545 "}\n\n"
a38c6d4c 2546 , name);
970ed795
EL
2547
2548 src=mputprintf(src,
af710487 2549 "int %s::XER_encode(const XERdescriptor_t& p_td, TTCN_Buffer& p_buf, "
2550 "unsigned int p_flavor, int p_indent, embed_values_enc_struct_t* emb_val) const\n{\n"
970ed795
EL
2551 " if (n_elements==-1) TTCN_error(\"Attempt to XER-encode an unbound record of\");\n" /* TODO type name */
2552 " int encoded_length=(int)p_buf.get_len();\n"
2553 " boolean e_xer = is_exer(p_flavor);\n"
2554 " boolean own_tag = !(e_xer && p_indent && ((p_td.xer_bits & (ANY_ELEMENT|ANY_ATTRIBUTES|UNTAGGED))\n"
2555 " || (p_flavor & USE_TYPE_ATTR)));\n"
2556 " boolean indenting = !is_canonical(p_flavor) && own_tag;\n"
2557 "%s" /* Factor out p_indent if not attribute */
2558 " if (n_elements==0) {\n" /* Empty record of */
2559 , name
a38c6d4c 2560 , force_gen_seof ? " if (indenting && !(p_td.xer_bits & XER_ATTRIBUTE)) do_indent(p_buf, p_indent);\n"
2561 : (sdef->xerAttribute ? "" : " if (indenting) do_indent(p_buf, p_indent);\n")
970ed795 2562 );
a38c6d4c 2563 if (force_gen_seof || sdef->xerAttribute) {
2564 src=mputprintf(src,
2565 " if (e_xer%s) {\n" /* Empty attribute. */
970ed795
EL
2566 " begin_attribute(p_td, p_buf);\n"
2567 " p_buf.put_c('\\'');\n"
a38c6d4c 2568 " } else\n"
2569 , force_gen_seof ? " && (p_td.xer_bits & XER_ATTRIBUTE)" : "");
970ed795 2570 }
a38c6d4c 2571 if (force_gen_seof || !sdef->xerAttribute) {
970ed795
EL
2572 src = mputstr(src,
2573 " if (own_tag)");
2574 }
2575 src=mputprintf(src,
2576 " {\n" /* Do empty element tag */
2577 "%s"
2578 " p_buf.put_c('<');\n"
2579 " if (e_xer) write_ns_prefix(p_td, p_buf);\n"
2580 " p_buf.put_s((size_t)p_td.namelens[e_xer]-2, (const unsigned char*)p_td.names[e_xer]);\n"
2581 /* namespace declarations for the toplevel element */
2582 " if (e_xer && p_indent==0)\n"
2583 " {\n"
2584 " size_t num_collected = 0;\n"
2585 " char **collected_ns = NULL;\n"
2586 " bool def_ns = false;\n"
2587 " collected_ns = collect_ns(p_td, num_collected, def_ns);\n"
2588 " for (size_t cur_coll = 0; cur_coll < num_collected; ++cur_coll) {\n"
2589 " p_buf.put_s(strlen(collected_ns[cur_coll]), (cbyte*)collected_ns[cur_coll]);\n"
2590 " Free(collected_ns[cur_coll]);\n"
2591 " }\n"
2592 " Free(collected_ns);\n"
2593 " }\n"
2594
2595 " p_buf.put_s(2 + indenting, (const unsigned char*)\"/>\\n\");\n"
2596 " }\n"
2597 " }\n"
2598 " else {\n" /* Not empty record of. Start tag or attribute */
a38c6d4c 2599 , force_gen_seof ? " if (indenting && !(p_td.xer_bits & XER_ATTRIBUTE)) do_indent(p_buf, p_indent);\n"
2600 : (sdef->xerAttribute ? "" : " if (indenting) do_indent(p_buf, p_indent);\n")
970ed795
EL
2601 );
2602 if (sdef->xerAnyAttrElem) {
2603 src = mputstr(src,
2604 " if (e_xer && (p_td.xer_bits & ANY_ATTRIBUTES)) {\n"
2605 " static const universal_char sp = { 0,0,0,' ' };\n"
2606 " static const universal_char tb = { 0,0,0,9 };\n"
2607 " size_t buf_len = p_buf.get_len(), shorter = 0;\n"
2608 " const unsigned char * const buf_data = p_buf.get_data();\n"
2609 " if (buf_data[buf_len - 1 - shorter] == '\\n') ++shorter;\n"
2610 " if (buf_data[buf_len - 1 - shorter] == '>' ) ++shorter;\n"
2611 " unsigned char saved[4];\n"
2612 " memcpy(saved, buf_data + (buf_len - shorter), shorter);\n"
2613 " p_buf.increase_length(-shorter);\n"
2614 " for (int i = 0; i < n_elements; ++i) {\n"
2615 " TTCN_EncDec_ErrorContext ec_0(\"Attribute %d: \", i);\n"
2616 " size_t len = value_elements[i].lengthof();\n"
2617 " for (;;) {\n"
2618 " const UNIVERSAL_CHARSTRING_ELEMENT& ue = value_elements[i][len - 1];\n"
2619 " if (sp == ue || tb == ue) --len;\n"
2620 " else break;\n"
2621 " }\n"
2622 " size_t j, sp_at = 0;\n"
2623 /* Find the "separators" in each string */
2624 " for (j = 0; j < len; j++) {\n"
2625 " UNIVERSAL_CHARSTRING_ELEMENT ue = value_elements[i][j];\n"
2626 " if (sp_at) {\n"
2627 " if (sp == ue || tb == ue) {}\n"
2628 " else break;\n"
2629 " } else {\n"
2630 " if (sp == ue || tb == ue) sp_at = j;\n"
2631 " }\n"
2632 " } // next j\n"
2633 " size_t buf_start = p_buf.get_len();\n"
2634 /* Now write them */
2635 " if (sp_at > 0) {\n"
2636 " char * ns = mprintf(\" xmlns:b%d='\", i);\n"
2637 " size_t ns_len = mstrlen(ns);\n"
2638 " p_buf.put_s(ns_len, (const unsigned char*)ns);\n"
2639
2640 " UNIVERSAL_CHARSTRING before(sp_at, (const universal_char*)(value_elements[i]));\n"
af710487 2641 " before.XER_encode(UNIVERSAL_CHARSTRING_xer_, p_buf, p_flavor | ANY_ATTRIBUTES, p_indent, 0);\n"
970ed795
EL
2642 // Ensure the namespace abides to its restrictions
2643 " if (p_td.xer_bits & (ANY_FROM | ANY_EXCEPT)) {\n"
2644 " TTCN_Buffer ns_buf;\n"
2645 " before.encode_utf8(ns_buf);\n"
2646 " CHARSTRING cs;\n"
2647 " ns_buf.get_string(cs);\n"
2648 " check_namespace_restrictions(p_td, (const char*)cs);\n"
2649 " }\n"
2650
2651 " p_buf.put_c('\\'');\n"
2652 " p_buf.put_c(' ');\n"
2653
2654 /* Keep just the "b%d" part from ns */
2655 " p_buf.put_s(ns_len - 9, (const unsigned char*)ns + 7);\n"
2656 " p_buf.put_c(':');\n"
2657 " Free(ns);\n"
2658 " }\n"
2659 " else {\n"
2660 " p_buf.put_c(' ');\n"
2661 " j = 0;\n"
2662 // Make sure the unqualified namespace is allowed
2663 " if (p_td.xer_bits & (ANY_FROM | ANY_EXCEPT)) {\n"
2664 " check_namespace_restrictions(p_td, NULL);\n"
2665 " }\n"
2666 " }\n"
2667
2668 " UNIVERSAL_CHARSTRING after(len - j, (const universal_char*)(value_elements[i]) + j);\n"
af710487 2669 " after.XER_encode(UNIVERSAL_CHARSTRING_xer_, p_buf, p_flavor | ANY_ATTRIBUTES, p_indent, 0);\n"
970ed795
EL
2670 // Put this attribute in a dummy element and walk through it to check its validity
2671 " TTCN_Buffer check_buf;\n"
2672 " check_buf.put_s(2, (unsigned char*)\"<a\");\n"
2673 " check_buf.put_s(p_buf.get_len() - buf_start, p_buf.get_data() + buf_start);\n"
2674 " check_buf.put_s(2, (unsigned char*)\"/>\");"
2675 " XmlReaderWrap checker(check_buf);\n"
2676 " while (1 == checker.Read()) ;\n"
2677 " }\n"
2678
2679 " p_buf.put_s(shorter, saved);\n" /* restore the '>' and anything after */
2680 " } else {\n");
2681 }
a38c6d4c 2682 if (force_gen_seof || sdef->xerAttribute) {
2683 src=mputprintf(src,
2684 " if (e_xer%s) {\n"
970ed795 2685 " begin_attribute(p_td, p_buf);\n"
a38c6d4c 2686 " } else\n"
2687 , force_gen_seof ? " && (p_td.xer_bits & XER_ATTRIBUTE)" : "");
970ed795
EL
2688 }
2689 src=mputprintf(src,
2690 " if (own_tag) {\n"
2691 "%s"
2692 " p_buf.put_c('<');\n"
2693 " boolean write_ns = (e_xer && p_indent==0);\n"
2694 " boolean keep_newline = (indenting && !(e_xer && (p_td.xer_bits & XER_LIST)));\n"
2695 " if (e_xer) write_ns_prefix(p_td, p_buf);\n"
2696 " p_buf.put_s((size_t)p_td.namelens[e_xer]-write_ns-(write_ns || !keep_newline), "
2697 "(const unsigned char*)p_td.names[e_xer]);\n"
2698
2699 /* namespace declarations for the toplevel element */
2700 " if (e_xer && p_indent==0)\n"
2701 " {\n"
2702 " size_t num_collected = 0;\n"
2703 " char **collected_ns = NULL;\n"
2704 " bool def_ns = false;\n"
2705 " collected_ns = collect_ns(p_td, num_collected, def_ns);\n"
2706 " for (size_t cur_coll = 0; cur_coll < num_collected; ++cur_coll) {\n"
2707 " p_buf.put_s(strlen(collected_ns[cur_coll]), (cbyte*)collected_ns[cur_coll]);\n"
2708 " Free(collected_ns[cur_coll]);\n"
2709 " }\n"
2710 " Free(collected_ns);\n"
2711 " p_buf.put_s(1 + keep_newline, (cbyte*)\">\\n\");\n"
2712 " }\n"
a38c6d4c 2713 , force_gen_seof ? " if (indenting && (p_td.xer_bits & XER_ATTRIBUTE)) do_indent(p_buf, p_indent);\n"
2714 : (sdef->xerAttribute ? " if (indenting) do_indent(p_buf, p_indent);\n" : "")
970ed795
EL
2715 );
2716 if (sdef->xmlValueList) {
2717 src=mputstr(src, " if (indenting && !e_xer) do_indent(p_buf, p_indent+1);\n"); /* !e_xer or GDMO */
2718 }
2719 src=mputstr(src,
2720 " }\n"
2721 " p_flavor |= XER_RECOF | (p_td.xer_bits & XER_LIST);\n"
2722 " TTCN_EncDec_ErrorContext ec_0(\"Index \");\n"
2723 " TTCN_EncDec_ErrorContext ec_1;\n"
2724 );
a38c6d4c 2725 src=mputstr(src,
970ed795 2726 " for (int i = 0; i < n_elements; ++i) {\n"
a38c6d4c 2727 " if (i > 0 && !own_tag && 0 != emb_val &&\n"
2728 " emb_val->embval_index < (0 != emb_val->embval_array_reg ?\n"
2729 " emb_val->embval_array_reg->size_of() : emb_val->embval_array_opt->size_of())) {\n"
2730 " if (0 != emb_val->embval_array_reg) {\n"
2731 " (*emb_val->embval_array_reg)[emb_val->embval_index].XER_encode(\n"
2732 " UNIVERSAL_CHARSTRING_xer_, p_buf, p_flavor | EMBED_VALUES, p_indent+1, 0);\n"
2733 " }\n"
2734 " else {\n"
2735 " (*emb_val->embval_array_opt)[emb_val->embval_index].XER_encode(\n"
2736 " UNIVERSAL_CHARSTRING_xer_, p_buf, p_flavor | EMBED_VALUES, p_indent+1, 0);\n"
2737 " }\n"
af710487 2738 " ++emb_val->embval_index;\n"
a38c6d4c 2739 " }\n"
2740 " ec_1.set_msg(\"%d: \", i);\n"
970ed795 2741 " if (e_xer && (p_td.xer_bits & XER_LIST) && i>0) p_buf.put_c(' ');\n"
a38c6d4c 2742 " value_elements[i].XER_encode(*p_td.oftype_descr, p_buf, p_flavor, p_indent+own_tag, emb_val);\n"
970ed795 2743 " }\n"
a38c6d4c 2744 " if (indenting && !is_exerlist(p_flavor)) {\n"
970ed795
EL
2745 );
2746 if (sdef->xmlValueList) {
2747 src=mputstr(src, " if (!e_xer) p_buf.put_c('\\n');\n"); /* !e_xer or GDMO */
2748 }
2749 src=mputstr(src,
2750 " do_indent(p_buf, p_indent);\n"
2751 " }\n");
a38c6d4c 2752 if (force_gen_seof || sdef->xerAttribute) {
2753 src=mputprintf(src,
2754 " if (e_xer%s) p_buf.put_c('\\'');\n"
2755 " else\n"
2756 , force_gen_seof ? " && (p_td.xer_bits & XER_ATTRIBUTE)" : "");
970ed795
EL
2757 }
2758 src=mputstr(src,
2759 " if (own_tag){\n"
2760 " p_buf.put_c('<');\n"
2761 " p_buf.put_c('/');\n"
2762 " if (e_xer) write_ns_prefix(p_td, p_buf);\n"
2763 " p_buf.put_s((size_t)p_td.namelens[e_xer]-!indenting, (const unsigned char*)p_td.names[e_xer]);\n"
2764 " }\n");
2765 if (sdef->xerAnyAttrElem) {
2766 src = mputstr(src, " }\n");
2767 }
2768 src=mputstr(src,
2769 " }\n" /* end if(no elements) */
2770 " return (int)p_buf.get_len() - encoded_length;\n"
2771 "}\n\n"
2772 );
2773
2774 src = mputprintf(src, /* XERSTUFF decoder codegen for record-of */
2775#ifndef NDEBUG
2776 "// written by %s in " __FILE__ " at %d\n"
2777#endif
2778 "int %s::XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& p_reader, "
af710487 2779 "unsigned int p_flavor, embed_values_dec_struct_t* emb_val)\n{\n"
970ed795
EL
2780 " boolean e_xer = is_exer(p_flavor);\n"
2781 " int xerbits = p_td.xer_bits;\n"
2782 " if (p_flavor & XER_TOPLEVEL) xerbits &= ~UNTAGGED;\n"
2783 " boolean own_tag = !(e_xer && ((xerbits & (ANY_ELEMENT|ANY_ATTRIBUTES|UNTAGGED))"
2784 " || (p_flavor & USE_TYPE_ATTR)));\n" /* incase the parent has USE-UNION */
2785 /* not toplevel anymore and remove the flags for USE-UNION the oftype doesn't need them */
2786 " p_flavor &= ~XER_TOPLEVEL & ~XER_LIST & ~USE_TYPE_ATTR;\n"
2787 " int rd_ok=1, xml_depth=-1;\n"
2788 " *this = NULL_VALUE;\n" /* empty but initialized array */
2789 " int type = 0;\n" /* none */
2790 " if (own_tag) for (rd_ok = p_reader.Ok(); rd_ok == 1; rd_ok = p_reader.Read()) {\n"
2791 " type = p_reader.NodeType();\n"
2792 " if (e_xer && (p_td.xer_bits & XER_ATTRIBUTE)) {\n"
2793 " if ((XML_READER_TYPE_ELEMENT == type && p_reader.MoveToFirstAttribute() == 1)\n"
2794 " || XML_READER_TYPE_ATTRIBUTE == type) {\n"
2795 " verify_name(p_reader, p_td, e_xer);\n"
2796 " break;"
2797 " }\n"
2798 " }\n"
2799 " if (e_xer && (p_td.xer_bits & XER_LIST)) {\n"
2800 " if (XML_READER_TYPE_TEXT == type) break;\n"
2801 " }\n"
2802 " else {\n"
2803 " if (XML_READER_TYPE_ELEMENT == type) {\n"
2804 " verify_name(p_reader, p_td, e_xer);\n"
2805 " xml_depth = p_reader.Depth();\n"
2806 " break;\n"
2807 " }\n"
2808 " }\n" /* endif(e_xer && list) */
2809 " }\n" /* next read */
2810 " else xml_depth = p_reader.Depth();\n"
2811 " p_flavor |= XER_RECOF;\n"
2812#ifndef NDEBUG
2813 , __FUNCTION__, __LINE__
2814#endif
2815 , name
2816 );
2817
a38c6d4c 2818 src = mputstr(src,
970ed795
EL
2819 " if (e_xer && (p_td.xer_bits & XER_LIST)) {\n" /* LIST decoding*/
2820 " char *x_val = (char*)p_reader.NewValue();\n" /* we own it */
2821 " size_t x_pos = 0;\n"
2822 " size_t x_len = strlen(x_val);\n"
2823 /* The string contains a bunch of values separated by whitespace.
2824 * Tokenize the string and create a new buffer which looks like
2825 * an XML element (<ns:name xmlns:ns='uri'>value</ns:name>),
2826 * then use that to decode the value. */
2827 " for(char * str = strtok(x_val, \" \\t\\x0A\\x0D\"); str != 0; str = strtok(x_val + x_pos, \" \\t\\x0A\\x0D\")) {\n"
2828 // Calling strtok with NULL won't work here, since the decoded element can have strtok calls aswell
2829 " x_pos += strlen(str) + 1;\n"
2830 " TTCN_Buffer buf_2;\n"
2831 " buf_2.put_c('<');\n"
a38c6d4c 2832 " write_ns_prefix(*p_td.oftype_descr, buf_2);\n"
2833 " const char * const exer_name = p_td.oftype_descr->names[1];\n"
2834 " boolean i_can_has_ns = p_td.oftype_descr->my_module != 0 && p_td.oftype_descr->ns_index != -1;\n"
970ed795 2835 /* If it has a namespace, chop off the '>' from the end */
a38c6d4c 2836 " buf_2.put_s((size_t)p_td.oftype_descr->namelens[1]-1-i_can_has_ns, (cbyte*)exer_name);\n"
970ed795 2837 " if (i_can_has_ns) {\n"
a38c6d4c 2838 " const namespace_t * const pns = p_td.oftype_descr->my_module->get_ns(p_td.oftype_descr->ns_index);\n"
970ed795
EL
2839 " buf_2.put_s(7 - (*pns->px == 0), (cbyte*)\" xmlns:\");\n"
2840 " buf_2.put_s(strlen(pns->px), (cbyte*)pns->px);\n"
2841 " buf_2.put_s(2, (cbyte*)\"='\");\n"
2842 " buf_2.put_s(strlen(pns->ns), (cbyte*)pns->ns);\n"
2843 " buf_2.put_s(2, (cbyte*)\"'>\");\n"
2844 " }\n"
2845 /* start tag completed */
2846 " buf_2.put_s(strlen(str), (cbyte*)str);\n"
2847 " buf_2.put_c('<');\n"
2848 " buf_2.put_c('/');\n"
a38c6d4c 2849 " write_ns_prefix(*p_td.oftype_descr, buf_2);\n"
2850 " buf_2.put_s((size_t)p_td.oftype_descr->namelens[1], (cbyte*)exer_name);\n"
970ed795
EL
2851 " XmlReaderWrap reader_2(buf_2);\n"
2852 " rd_ok = reader_2.Read();\n" /* Move to the start element. */
2853 /* Don't move to the #text, that's the callee's responsibility. */
2854 /* The call to the non-const operator[] creates a new element object,
2855 * then we call its XER_decode with the temporary XML reader. */
a38c6d4c 2856 " (*this)[n_elements].XER_decode(*p_td.oftype_descr, reader_2, p_flavor, 0);\n"
970ed795
EL
2857 " if (p_flavor & EXIT_ON_ERROR && !(*this)[n_elements - 1].is_bound()) {\n"
2858 " if (1 == n_elements) {\n"
2859 // Failed to decode even the first element
2860 " clean_up();\n"
2861 " } else {\n"
2862 // Some elements were successfully decoded -> only delete the last one
2863 " set_size(n_elements - 1);\n"
2864 " }\n"
2865 " xmlFree(x_val);\n"
2866 " return -1;\n"
2867 " }\n"
2868 " if (x_pos >= x_len) break;\n"
2869 " }\n"
2870 " xmlFree(x_val);\n"
2871 " if ((p_td.xer_bits & XER_ATTRIBUTE)) ;\n"
2872 /* Let the caller do AdvanceAttribute() */
2873 " else if (own_tag) {\n"
2874 " p_reader.Read();\n" /* on closing tag */
2875 " p_reader.Read();\n" /* past it */
2876 " }\n"
2877 " }\n"
970ed795
EL
2878 );
2879
2880 src = mputprintf(src,
2881 " else {\n"
2882 " if (p_flavor & PARENT_CLOSED) ;\n"
2883 /* Nothing to do, but do not advance past the parent's element */
2884 " else if (own_tag && p_reader.IsEmptyElement()) rd_ok = p_reader.Read();\n"
2885 /* It's our XML empty element: nothing to do, skip past it */
2886 " else {\n"
2887 /* Note: there is no p_reader.Read() at the end of the loop below.
2888 * Each element is supposed to consume enough to leave the next element
2889 * well-positioned. */
2890 " for (rd_ok = own_tag ? p_reader.Read() : p_reader.Ok(); rd_ok == 1; ) {\n"
2891 " type = p_reader.NodeType();\n"
2892 " if (XML_READER_TYPE_ELEMENT == type)\n"
2893 " {\n");
2894 if (sdef->xerAnyAttrElem) {
2895 src = mputprintf(src,
2896 " if (e_xer && (p_td.xer_bits & ANY_ELEMENT)) {\n"
2897 /* This is a record-of with ANY-ELEMENT applied, which is really meant
2898 * for the element type (a string), so behave like a record-of
2899 * (string with ANY-ELEMENT): call the non-const operator[]
2900 * to create a new element, then read the entire XML element into it. */
2901 " (*this)[n_elements] = (const char*)p_reader.ReadOuterXml();\n"
2902 /* Consume the element, then move ahead */
2903 " for (rd_ok = p_reader.Read(); rd_ok == 1 && p_reader.Depth() > xml_depth; rd_ok = p_reader.Read()) {}\n"
2904 " if (p_reader.NodeType() != XML_READER_TYPE_ELEMENT) rd_ok = p_reader.Read();\n"
2905 " } else");
2906 }
a38c6d4c 2907 src = mputstr(src,
970ed795
EL
2908 " {\n"
2909 /* An untagged record-of ends if it encounters an element with a name
2910 * that doesn't match its component */
2911 " if (!own_tag && !can_start((const char*)p_reader.LocalName(), "
a38c6d4c 2912 "(const char*)p_reader.NamespaceUri(), p_td, p_flavor)) {\n"
970ed795
EL
2913 " for (; rd_ok == 1 && p_reader.Depth() > xml_depth; rd_ok = p_reader.Read()) ;\n"
2914 " break;\n"
2915 " }\n"
2916 /* The call to the non-const operator[] creates the element */
a38c6d4c 2917 " operator [](n_elements).XER_decode(*p_td.oftype_descr, p_reader, p_flavor, emb_val);\n"
af710487 2918 " if (0 != emb_val && !own_tag && n_elements > 1) {\n"
2919 " ++emb_val->embval_index;\n"
2920 " }\n"
970ed795
EL
2921 " }\n"
2922 " }\n"
2923 " else if (XML_READER_TYPE_END_ELEMENT == type) {\n"
2924 " for (; p_reader.Depth() > xml_depth; rd_ok = p_reader.Read()) ;\n"
2925 " if (own_tag) {\n"
2926 " verify_end(p_reader, p_td, xml_depth, e_xer);\n"
2927 " rd_ok = p_reader.Read();\n" /* move forward one last time */
2928 " }\n"
2929 " break;\n"
2930 " }\n"
a38c6d4c 2931 " else if (XML_READER_TYPE_TEXT == type && 0 != emb_val && !own_tag && n_elements > 0) {\n"
af710487 2932 " UNIVERSAL_CHARSTRING emb_ustr((const char*)p_reader.Value());\n"
a38c6d4c 2933 " if (0 != emb_val->embval_array_reg) {\n"
2934 " (*emb_val->embval_array_reg)[emb_val->embval_index] = emb_ustr;\n"
2935 " }\n"
2936 " else {\n"
2937 " (*emb_val->embval_array_opt)[emb_val->embval_index] = emb_ustr;\n"
2938 " }\n"
af710487 2939 " rd_ok = p_reader.Read();\n"
a38c6d4c 2940 " }\n"
970ed795
EL
2941 " else {\n"
2942 " rd_ok = p_reader.Read();\n"
2943 " }\n"
2944 " }\n" /* next read */
2945 " }\n" /* if not empty element */
2946 " }\n" /* if not LIST */
2947 " return 1;\n"
2948 "}\n\n"
970ed795
EL
2949 );
2950 }
2951 if (json_needed) {
2952 // JSON encode, RT1, mem. alloc. optimised
2953 src = mputprintf(src,
a38c6d4c 2954 "int %s::JSON_encode(const TTCN_Typedescriptor_t& p_td, JSON_Tokenizer& p_tok) const\n"
970ed795
EL
2955 "{\n"
2956 " if (!is_bound()) {\n"
2957 " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND,\n"
2958 " \"Encoding an unbound value of type %s.\");\n"
2959 " return -1;\n"
2960 " }\n\n"
2961 " int enc_len = p_tok.put_next_token(JSON_TOKEN_ARRAY_START, NULL);\n"
2962 " for(int i = 0; i < n_elements; ++i) {\n"
a38c6d4c 2963 " int ret_val = value_elements[i].JSON_encode(*p_td.oftype_descr, p_tok);\n"
970ed795
EL
2964 " if (0 > ret_val) break;\n"
2965 " enc_len += ret_val;\n"
2966 " }\n"
2967 " enc_len += p_tok.put_next_token(JSON_TOKEN_ARRAY_END, NULL);\n"
2968 " return enc_len;\n"
2969 "}\n\n"
a38c6d4c 2970 , name, dispname);
970ed795
EL
2971
2972 // JSON decode, RT1, mem. alloc. optimised
2973 src = mputprintf(src,
a38c6d4c 2974 "int %s::JSON_decode(const TTCN_Typedescriptor_t& p_td, JSON_Tokenizer& p_tok, boolean p_silent)\n"
970ed795
EL
2975 "{\n"
2976 " json_token_t token = JSON_TOKEN_NONE;\n"
2977 " int dec_len = p_tok.get_next_token(&token, NULL, NULL);\n"
2978 " if (JSON_TOKEN_ERROR == token) {\n"
2979 " JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_BAD_TOKEN_ERROR, \"\");\n"
2980 " return JSON_ERROR_FATAL;\n"
2981 " }\n"
2982 " else if (JSON_TOKEN_ARRAY_START != token) {\n"
2983 " return JSON_ERROR_INVALID_TOKEN;\n"
2984 " }\n\n"
2985 " set_size(0);\n"
2986 " while (true) {\n"
2987 " size_t buf_pos = p_tok.get_buf_pos();\n"
2988 " %s val;\n"
a38c6d4c 2989 " int ret_val = val.JSON_decode(*p_td.oftype_descr, p_tok, p_silent);\n"
970ed795
EL
2990 " if (JSON_ERROR_INVALID_TOKEN == ret_val) {\n"
2991 " p_tok.set_buf_pos(buf_pos);\n"
2992 " break;\n"
2993 " }\n"
2994 " else if (JSON_ERROR_FATAL == ret_val) {\n"
2995 " if (p_silent) {\n"
2996 " clean_up();\n"
2997 " }\n"
2998 " return JSON_ERROR_FATAL;\n"
2999 " }\n"
3000 " set_size(n_elements + 1);\n"
3001 " value_elements[n_elements - 1] = val;\n"
3002 " dec_len += ret_val;\n"
3003 " }\n\n"
3004 " dec_len += p_tok.get_next_token(&token, NULL, NULL);\n"
3005 " if (JSON_TOKEN_ARRAY_END != token) {\n"
3006 " JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_REC_OF_END_TOKEN_ERROR, \"\");\n"
3007 " if (p_silent) {\n"
3008 " clean_up();\n"
3009 " }\n"
3010 " return JSON_ERROR_FATAL;\n"
3011 " }\n\n"
3012 " return dec_len;\n"
3013 "}\n\n"
a38c6d4c 3014 , name, type);
970ed795 3015 }
970ed795
EL
3016 /* end of class */
3017 def = mputstr(def, "};\n\n");
3018
3019 output->header.class_decls = mputprintf(output->header.class_decls,
3020 "class %s;\n", name);
3021 output->header.class_defs = mputstr(output->header.class_defs, def);
3022 Free(def);
3023 output->source.methods = mputstr(output->source.methods, src);
3024 Free(src);
3025 /* Copied from record.c. */
3026 output->header.function_prototypes =
3027 mputprintf(output->header.function_prototypes,
3028 "extern boolean operator==(null_type null_value, const %s& "
3029 "other_value);\n", name);
3030 output->source.function_bodies =
3031 mputprintf(output->source.function_bodies,
3032 "boolean operator==(null_type, const %s& other_value)\n"
3033 "{\n"
3034 "if (other_value.n_elements==-1)\n"
3035 "TTCN_error(\"The right operand of comparison is an unbound value of "
3036 "type %s.\");\n"
3037 "return other_value.n_elements == 0;\n"
3038 "}\n\n", name, dispname);
3039
3040 output->header.function_prototypes =
3041 mputprintf(output->header.function_prototypes,
3042 "inline boolean operator!=(null_type null_value, const %s& "
3043 "other_value) "
3044 "{ return !(null_value == other_value); }\n", name);
3045}
3046
3047/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
3048
3049void defRecordOfClass2(const struct_of_def *sdef, output_struct *output)
3050{
3051 char *def = NULL, *src = NULL;
3052 const char *name = sdef->name;
3053 const char *type = sdef->type;
a38c6d4c 3054 boolean raw_needed = force_gen_seof || (sdef->hasRaw && enable_raw());
3055 boolean xer_needed = force_gen_seof || (sdef->hasXer && enable_xer());
970ed795
EL
3056
3057 /* Class definition */
3058 def = mputprintf(def,
3059 "class %s : public Record_Of_Type {\n", name);
3060
3061 /* constant unbound element */
3062 def = mputprintf(def, "\nstatic const %s UNBOUND_ELEM;\n", type);
3063 src = mputprintf(src, "\nconst %s %s::UNBOUND_ELEM;\n", type, name);
3064
3065 /* public member functions */
3066 def = mputstr(def, "\npublic:\n");
3067
3068 /* constructors */
3069 def = mputprintf(def, "%s(): Record_Of_Type() {}\n", name);
3070 def = mputprintf(def, "%s(null_type other_value): Record_Of_Type(other_value) {}\n", name);
3071 /* copy constructor */
3072 def = mputprintf(def, "%s(const %s& other_value): Record_Of_Type(other_value) {}\n", name, name);
3073 /* destructor */
3074 def = mputprintf(def, "~%s() { clean_up(); }\n\n", name);
3075
3076 /* assignment operators */
3077 def = mputprintf(def, "inline %s& operator=(null_type other_value) "
3078 "{ set_val(other_value); return *this; }\n", name);
3079 def = mputprintf(def, "inline %s& operator=(const %s& other_value) "
3080 "{ set_value(&other_value); return *this; }\n\n", name, name);
3081
3082 /* comparison operators */
3083 def = mputprintf(def, "inline boolean operator==(const %s& other_value) const "
3084 "{ return is_equal(&other_value); }\n", name);
3085 def = mputprintf(def, "boolean operator!=(const %s& other_value) const "
3086 "{ return !is_equal(&other_value); }\n", name);
3087
3088 /* indexing operators */
3089 def = mputprintf(def,
3090 "%s& operator[](int index_value);\n"
3091 "%s& operator[](const INTEGER& index_value);\n"
3092 "const %s& operator[](int index_value) const;\n"
3093 "const %s& operator[](const INTEGER& index_value) const;\n",
3094 type,
3095 type,
3096 type,
3097 type);
3098
3099 src = mputprintf(src,
3100 "%s& %s::operator[](int index_value) { return *(static_cast<%s*>(get_at(index_value))); }\n"
3101 "%s& %s::operator[](const INTEGER& index_value) { return *(static_cast<%s*>(get_at(index_value))); }\n"
3102 "const %s& %s::operator[](int index_value) const { return *(static_cast<const %s*>(get_at(index_value))); }\n"
3103 "const %s& %s::operator[](const INTEGER& index_value) const { return *(static_cast<const %s*>(get_at(index_value))); }\n\n",
3104 type, name, type,
3105 type, name, type,
3106 type, name, type,
3107 type, name, type);
3108
3109 /* rotation operators */
3110 def = mputprintf(def,
3111 "%s operator<<=(int rotate_count) const;\n"
3112 "%s operator<<=(const INTEGER& rotate_count) const;\n"
3113 "%s operator>>=(int rotate_count) const;\n"
3114 "%s operator>>=(const INTEGER& rotate_count) const;\n\n",
3115 name, name, name, name);
3116 src = mputprintf(src,
3117 "%s %s::operator<<=(int rotate_count) const\n"
3118 "{\n"
3119 "return *this >>= (-rotate_count);\n"
3120 "}\n\n"
3121 "%s %s::operator<<=(const INTEGER& rotate_count) const\n"
3122 "{\n"
3123 "%s rec_of;\n"
3124 "return *((%s*)rotl(rotate_count, &rec_of));\n"
3125 "}\n\n"
3126 "%s %s::operator>>=(const INTEGER& rotate_count) const\n"
3127 "{\n"
3128 "%s rec_of;\n"
3129 "return *((%s*)rotr(rotate_count, &rec_of));\n"
3130 "}\n\n"
3131 "%s %s::operator>>=(int rotate_count) const\n"
3132 "{\n"
3133 "%s rec_of;\n"
3134 "return *((%s*)rotr(rotate_count, &rec_of));\n"
3135 "}\n\n",
3136 name, name, name, name, name, name, name, name, name, name, name,
3137 name, name, name);
3138
3139 /* concatenation */
3140 def = mputprintf(def,
3141 "%s operator+(const %s& other_value) const;\n\n", name, name);
3142 src = mputprintf(src,
3143 "%s %s::operator+(const %s& other_value) const\n"
3144 "{\n"
3145 "%s rec_of;\n"
3146 "return *((%s*)concat(&other_value, &rec_of));\n"
3147 "}\n\n", name, name, name, name, name);
3148
3149 /* substr() */
3150 def = mputprintf(def,
3151 "%s substr(int index, int returncount) const;\n\n", name);
3152 src = mputprintf(src,
3153 "%s %s::substr(int index, int returncount) const\n"
3154 "{\n"
3155 "%s rec_of;\n"
3156 "substr_(index, returncount, &rec_of);\n"
3157 "return rec_of;\n"
3158 "}\n\n", name, name, name);
3159
3160 /* replace() */
3161 def = mputprintf(def,
3162 "%s replace(int index, int len, const %s& repl) const;\n\n", name, name);
3163 src = mputprintf(src,
3164 "%s %s::replace(int index, int len, const %s& repl) const\n"
3165 "{\n"
3166 "%s rec_of;\n"
3167 "replace_(index, len, &repl, &rec_of);\n"
3168 "return rec_of;\n"
3169 "}\n\n", name, name, name, name);
3170 def = mputprintf(def,
3171 "%s replace(int index, int len, const %s_template& repl) const;\n\n",
3172 name, name);
3173 src = mputprintf(src,
3174 "%s %s::replace(int index, int len, const %s_template& repl) const\n"
3175 "{\n"
3176 "%s rec_of;\n"
3177 "replace_(index, len, &repl, &rec_of);\n"
3178 "return rec_of;\n"
3179 "}\n\n", name, name, name, name);
3180
3181 def = mputprintf(def,
3182 "Base_Type* clone() const { return new %s(*this); }\n"
3183 "const TTCN_Typedescriptor_t* get_descriptor() const;\n"
3184 "const TTCN_Typedescriptor_t* get_elem_descr() const;\n"
3185 "Base_Type* create_elem() const;\n"
3186 "const Base_Type* get_unbound_elem() const;\n"
3187 "boolean is_set() const { return %s; }\n",
3188 name,
3189 (sdef->kind == SET_OF) ? "TRUE" : "FALSE");
3190
3191 src = mputprintf(src,
3192 "Base_Type* %s::create_elem() const { return new %s; }\n"
3193 "const Base_Type* %s::get_unbound_elem() const { return &UNBOUND_ELEM; }\n"
a38c6d4c 3194 "const TTCN_Typedescriptor_t* %s::get_descriptor() const { return &%s_descr_; }\n",
970ed795
EL
3195 name, type,
3196 name,
a38c6d4c 3197 name, name);
970ed795
EL
3198
3199 /* helper functions called by enc/dec members of the ancestor class */
3200 if (raw_needed) {
3201 def = mputprintf(def, "int rawdec_ebv() const { return %d; }\n",
3202 (int)sdef->raw.extension_bit);
3203 }
3204 if (xer_needed) {
3205 def = mputprintf(def, "boolean isXerAttribute() const { return %s; }\n"
3206 "virtual boolean can_start_v(const char * name, const char *uri, "
3207 "XERdescriptor_t const& xd, unsigned int);\n"
3208 "static boolean can_start (const char * name, const char *uri, "
3209 "XERdescriptor_t const& xd, unsigned int);\n",
3210 sdef->xerAttribute ? "TRUE" : "FALSE");
3211 src = mputprintf(src,
3212 /* The virtual can_start_v hands off to the static can_start.
3213 * We must make a virtual call in Record_Of_Type::XER_decode because
3214 * we don't know the actual type (derived from Record_Of_Type) */
3215 "boolean %s::can_start_v(const char *name, const char *uri, "
3216 "XERdescriptor_t const& xd, unsigned int flavor) {\n"
3217 " return can_start(name, uri, xd, flavor);\n"
3218 "}\n\n"
3219 "boolean %s::can_start(const char *name, const char *uri, "
3220 "XERdescriptor_t const& xd, unsigned int flavor) {\n"
3221 " boolean e_xer = is_exer(flavor);\n"
a38c6d4c 3222 /* if EXER and UNTAGGED, it can begin with the tag of the element,
3223 * otherwise it must be the tag of the type itself,
3224 * specified in the supplied parameter.
3225 * If flavor contains UNTAGGED, that's a signal to go directly
3226 * to the embedded type. */
3227 " if (!e_xer || !((xd.xer_bits|flavor) & UNTAGGED)) return "
3228 "check_name(name, xd, e_xer) && (!e_xer || check_namespace(uri, xd));\n"
970ed795
EL
3229 /* a record-of with ANY-ELEMENT can start with any tag
3230 * :-( with some exceptions )-: */
a38c6d4c 3231 " if (e_xer && (xd.oftype_descr->xer_bits & ANY_ELEMENT)) "
970ed795
EL
3232 , name, name
3233 );
3234
a38c6d4c 3235 if (!force_gen_seof && sdef->nFollowers) {
970ed795
EL
3236 size_t f;
3237 src = mputstr(src, "{\n");
3238 for (f = 0; f < sdef->nFollowers; ++f) {
3239 src = mputprintf(src,
3240 " if (%s::can_start(name, uri, %s_xer_, flavor)) return FALSE;\n"
3241 , sdef->followers[f].type
3242 , sdef->followers[f].typegen
3243 );
3244 }
3245 src = mputstr(src,
3246 " return TRUE;\n"
3247 " }\n");
3248 }
3249 else {
3250 src = mputstr(src, "return TRUE;\n");
3251 }
3252 src = mputprintf(src,
a38c6d4c 3253 " return %s::can_start(name, uri, *xd.oftype_descr, flavor | XER_RECOF);\n"
3254 "}\n\n", sdef->type);
970ed795
EL
3255 def = mputprintf(def, "boolean isXmlValueList() const { return %s; }\n\n",
3256 sdef->xmlValueList ? "TRUE" : "FALSE");
3257 }
3258 else {
3259 /* The call in XER_decode is still there, can_start_v must exist. */
3260 def = mputstr(def,
3261 "virtual boolean can_start_v(const char *, const char *, "
3262 "XERdescriptor_t const&, unsigned int) { return FALSE; }\n");
3263 }
3264
3265 /* end of class */
3266 def = mputstr(def, "};\n\n");
3267
3268 output->header.class_decls = mputprintf(output->header.class_decls,
3269 "class %s;\n", name);
3270 output->header.class_defs = mputstr(output->header.class_defs, def);
3271 Free(def);
3272 output->source.methods = mputstr(output->source.methods, src);
3273 Free(src);
3274}
3275
3276/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
3277
3278void defRecordOfTemplate1(const struct_of_def *sdef, output_struct *output)
3279{
3280 char *def = NULL, *src = NULL;
3281 const char *name = sdef->name, *dispname = sdef->dispname;
3282 const char *type = sdef->type;
3283 const char *base_class = sdef->kind == RECORD_OF ? "Record_Of_Template" :
3284 "Restricted_Length_Template";
3285
3286 /* Class definition and private data members */
3287 def = mputprintf(def,
3288 "class %s_template : public %s {\n"
3289 "union {\n"
3290 "struct {\n"
3291 "int n_elements;\n"
3292 "%s_template **value_elements;\n"
3293 "} single_value;\n"
3294 "struct {\n"
3295 "unsigned int n_values;\n"
3296 "%s_template *list_value;\n"
3297 "} value_list;\n", name, base_class, type, name);
3298 if (sdef->kind == SET_OF) {
3299 def = mputprintf(def,
3300 "struct {\n"
3301 "unsigned int n_items;\n"
3302 "%s_template *set_items;\n"
3303 "} value_set;\n", type);
3304 }
3305 def = mputstr(def, "};\n");
3306
3307 /* private member functions */
3308
3309 /* copy_value function */
3310 def = mputprintf(def, "void copy_value(const %s& other_value);\n", name);
3311 src = mputprintf(src,
3312 "void %s_template::copy_value(const %s& other_value)\n"
3313 "{\n"
3314 "if (!other_value.is_bound()) "
3315 "TTCN_error(\"Initialization of a template of type %s with an unbound "
3316 "value.\");\n"
3317 "single_value.n_elements = other_value.size_of();\n"
3318 "single_value.value_elements = "
3319 "(%s_template**)allocate_pointers(single_value.n_elements);\n"
3320 "for (int elem_count = 0; elem_count < single_value.n_elements; "
3321 "elem_count++) {\n"
3322 "if (other_value[elem_count].is_bound()) {\n"
3323 "single_value.value_elements[elem_count] = "
3324 "new %s_template(other_value[elem_count]);\n"
3325 "} else {\n"
3326 "single_value.value_elements[elem_count] = new %s_template;\n"
3327 "}\n"
3328 "}\n"
3329 "set_selection(SPECIFIC_VALUE);\n"
3330 "}\n\n", name, name, dispname, type, type, type);
3331
3332 /* copy_template function */
3333 def = mputprintf(def, "void copy_template(const %s_template& "
3334 "other_value);\n", name);
3335 src = mputprintf(src,
3336 "void %s_template::copy_template(const %s_template& other_value)\n"
3337 "{\n"
3338 "switch (other_value.template_selection) {\n"
3339 "case SPECIFIC_VALUE:\n"
3340 "single_value.n_elements = other_value.single_value.n_elements;\n"
3341 "single_value.value_elements = "
3342 "(%s_template**)allocate_pointers(single_value.n_elements);\n"
3343 "for (int elem_count = 0; elem_count < single_value.n_elements; "
3344 "elem_count++) {\n"
3345 "if (UNINITIALIZED_TEMPLATE != "
3346 "other_value.single_value.value_elements[elem_count]->get_selection()) {\n"
3347 "single_value.value_elements[elem_count] = new %s_template"
3348 "(*other_value.single_value.value_elements[elem_count]);\n"
3349 "} else {\n"
3350 "single_value.value_elements[elem_count] = new %s_template;\n"
3351 "}\n"
3352 "}\n"
3353 "case OMIT_VALUE:\n"
3354 "case ANY_VALUE:\n"
3355 "case ANY_OR_OMIT:\n"
3356 "break;\n"
3357 "case VALUE_LIST:\n"
3358 "case COMPLEMENTED_LIST:\n"
3359 "value_list.n_values = other_value.value_list.n_values;\n"
3360 "value_list.list_value = new %s_template[value_list.n_values];\n"
3361 "for (unsigned int list_count = 0; list_count < value_list.n_values; "
3362 "list_count++)\n"
3363 "value_list.list_value[list_count].copy_template("
3364 "other_value.value_list.list_value[list_count]);\n"
3365 "break;\n", name, name, type, type, type, name);
3366 if (sdef->kind == SET_OF) {
3367 src = mputprintf(src,
3368 "case SUPERSET_MATCH:\n"
3369 "case SUBSET_MATCH:\n"
3370 "value_set.n_items = other_value.value_set.n_items;\n"
3371 "value_set.set_items = new %s_template[value_set.n_items];\n"
3372 "for (unsigned int set_count = 0; set_count < value_set.n_items; "
3373 "set_count++)\n"
3374 "value_set.set_items[set_count] = "
3375 "other_value.value_set.set_items[set_count];\n"
3376 "break;\n", type);
3377 }
3378 src = mputprintf(src,
3379 "default:\n"
3380 "TTCN_error(\"Copying an uninitialized/unsupported template of type "
3381 "%s.\");\n"
3382 "break;\n"
3383 "}\n"
3384 "set_selection(other_value);\n"
3385 "}\n\n", dispname);
3386
3387 /* callback function for matching specific values */
3388 def = mputstr(def,
3389 "static boolean match_function_specific(const Base_Type *value_ptr, "
3390 "int value_index, const Restricted_Length_Template *template_ptr, "
3391 "int template_index);\n");
3392 src = mputprintf(src,
3393 "boolean %s_template::match_function_specific(const Base_Type *value_ptr, "
3394 "int value_index, const Restricted_Length_Template *template_ptr, "
3395 "int template_index)\n"
3396 "{\n"
3397 "if (value_index >= 0) return ((const %s_template*)template_ptr)->"
3398 "single_value.value_elements[template_index]->"
3399 "match((*(const %s*)value_ptr)[value_index]);\n"
3400 "else return ((const %s_template*)template_ptr)->"
3401 "single_value.value_elements[template_index]->is_any_or_omit();\n"
3402 "}\n\n", name, name, name, name);
3403
3404 if (sdef->kind == SET_OF) {
3405 /* callback function for matching superset and subset */
3406 def = mputstr(def,
3407 "static boolean match_function_set(const Base_Type *value_ptr, "
3408 "int value_index, const Restricted_Length_Template *template_ptr, "
3409 "int template_index);\n");
3410 src = mputprintf(src,
3411 "boolean %s_template::match_function_set(const Base_Type *value_ptr, "
3412 "int value_index, const Restricted_Length_Template *template_ptr, "
3413 "int template_index)\n"
3414 "{\n"
3415 "if (value_index >= 0) return ((const %s_template*)template_ptr)->"
3416 "value_set.set_items[template_index].match("
3417 "(*(const %s*)value_ptr)[value_index]);\n"
3418 "else return ((const %s_template*)template_ptr)->"
3419 "value_set.set_items[template_index].is_any_or_omit();\n"
3420 "}\n\n", name, name, name, name);
3421
3422 /* callback function for log_match_heuristics */
3423 def = mputstr(def,
3424 "static void log_function(const Base_Type *value_ptr, "
3425 "const Restricted_Length_Template *template_ptr,"
3426 " int index_value, int index_template);\n");
3427 src = mputprintf(src,
3428 "void %s_template::log_function(const Base_Type *value_ptr, "
3429 "const Restricted_Length_Template *template_ptr,"
3430 " int index_value, int index_template)\n"
3431 "{\n"
3432 "if (value_ptr != NULL && template_ptr != NULL)"
3433 "((const %s_template*)template_ptr)"
3434 "->single_value.value_elements[index_template]"
3435 "->log_match((*(const %s*)value_ptr)[index_value]);\n"
3436 "else if (value_ptr != NULL) (*(const %s*)value_ptr)[index_value].log();\n"
3437 "else if (template_ptr != NULL) ((const %s_template*)template_ptr)"
3438 "->single_value.value_elements[index_template]->log();\n"
3439 "}\n\n", name, name, name, name, name);
3440 }
3441
3442 /* public member functions */
3443 def = mputstr(def, "\npublic:\n");
3444
3445 /* constructors */
3446 def = mputprintf(def, "%s_template();\n", name);
3447 src = mputprintf(src, "%s_template::%s_template()\n"
3448 "{\n"
3449 "}\n\n", name, name);
3450
3451 def = mputprintf(def, "%s_template(template_sel other_value);\n", name);
3452 src = mputprintf(src, "%s_template::%s_template(template_sel other_value)\n"
3453 " : %s(other_value)\n"
3454 "{\n"
3455 "check_single_selection(other_value);\n"
3456 "}\n\n", name, name, base_class);
3457
3458 def = mputprintf(def, "%s_template(null_type other_value);\n", name);
3459 src = mputprintf(src, "%s_template::%s_template(null_type)\n"
3460 " : %s(SPECIFIC_VALUE)\n"
3461 "{\n"
3462 "single_value.n_elements = 0;\n"
3463 "single_value.value_elements = NULL;\n"
3464 "}\n\n", name, name, base_class);
3465
3466 def = mputprintf(def, "%s_template(const %s& other_value);\n", name, name);
3467 src = mputprintf(src, "%s_template::%s_template(const %s& other_value)\n"
3468 "{\n"
3469 "copy_value(other_value);\n"
3470 "}\n\n", name, name, name);
3471
3472 def = mputprintf(def, "%s_template(const OPTIONAL<%s>& other_value);\n",
3473 name, name);
3474 src = mputprintf(src,
3475 "%s_template::%s_template(const OPTIONAL<%s>& other_value)\n"
3476 "{\n"
3477 "switch (other_value.get_selection()) {\n"
3478 "case OPTIONAL_PRESENT:\n"
3479 "copy_value((const %s&)other_value);\n"
3480 "break;\n"
3481 "case OPTIONAL_OMIT:\n"
3482 "set_selection(OMIT_VALUE);\n"
3483 "break;\n"
3484 "default:\n"
3485 "TTCN_error(\"Creating a template of type %s from an unbound optional "
3486 "field.\");\n"
3487 "}\n"
3488 "}\n\n", name, name, name, name, dispname);
3489
3490 /* copy constructor */
3491 def = mputprintf(def, "%s_template(const %s_template& other_value);\n",
3492 name, name);
3493 src = mputprintf(src,
3494 "%s_template::%s_template(const %s_template& other_value)\n"
3495 " : %s()\n"
3496 "{\n"
3497 "copy_template(other_value);\n"
3498 "}\n\n", name, name, name, base_class);
3499
3500 /* destructor */
3501 def = mputprintf(def, "~%s_template();\n\n", name);
3502 src = mputprintf(src,
3503 "%s_template::~%s_template()\n"
3504 "{\n"
3505 "clean_up();\n"
3506 "}\n\n", name, name);
3507
3508 /* clean_up function */
3509 def = mputstr(def, "void clean_up();\n");
3510 src = mputprintf(src,
3511 "void %s_template::clean_up()\n"
3512 "{\n"
3513 "switch (template_selection) {\n"
3514 "case SPECIFIC_VALUE:\n"
3515 "for (int elem_count = 0; elem_count < single_value.n_elements; "
3516 "elem_count++)\n"
3517 "delete single_value.value_elements[elem_count];\n"
3518 "free_pointers((void**)single_value.value_elements);\n"
3519 "break;\n"
3520 "case VALUE_LIST:\n"
3521 "case COMPLEMENTED_LIST:\n"
3522 "delete [] value_list.list_value;\n", name);
3523 if (sdef->kind == SET_OF) {
3524 src = mputstr(src,
3525 "break;\n"
3526 "case SUPERSET_MATCH:\n"
3527 "case SUBSET_MATCH:\n"
3528 "delete [] value_set.set_items;\n");
3529 }
3530 src = mputstr(src,
3531 "default:\n"
3532 "break;\n"
3533 "}\n"
3534 "template_selection = UNINITIALIZED_TEMPLATE;\n"
3535 "}\n\n");
3536
3537 /* assignment operators */
3538 def = mputprintf(def, "%s_template& operator=(template_sel other_value);\n",
3539 name);
3540 src = mputprintf(src,
3541 "%s_template& %s_template::operator=(template_sel other_value)\n"
3542 "{\n"
3543 "check_single_selection(other_value);\n"
3544 "clean_up();\n"
3545 "set_selection(other_value);\n"
3546 "return *this;\n"
3547 "}\n\n", name, name);
3548
3549 def = mputprintf(def, "%s_template& operator=(null_type other_value);\n",
3550 name);
3551 src = mputprintf(src,
3552 "%s_template& %s_template::operator=(null_type)\n"
3553 "{\n"
3554 "clean_up();\n"
3555 "set_selection(SPECIFIC_VALUE);\n"
3556 "single_value.n_elements = 0;\n"
3557 "single_value.value_elements = NULL;\n"
3558 "return *this;\n"
3559 "}\n\n", name, name);
3560
3561 def = mputprintf(def, "%s_template& operator=(const %s& other_value);\n",
3562 name, name);
3563 src = mputprintf(src,
3564 "%s_template& %s_template::operator=(const %s& other_value)\n"
3565 "{\n"
3566 "clean_up();\n"
3567 "copy_value(other_value);\n"
3568 "return *this;\n"
3569 "}\n\n", name, name, name);
3570
3571 def = mputprintf(def, "%s_template& operator=(const OPTIONAL<%s>& "
3572 "other_value);\n", name, name);
3573 src = mputprintf(src,
3574 "%s_template& %s_template::operator=(const OPTIONAL<%s>& other_value)\n"
3575 "{\n"
3576 "clean_up();\n"
3577 "switch (other_value.get_selection()) {\n"
3578 "case OPTIONAL_PRESENT:\n"
3579 "copy_value((const %s&)other_value);\n"
3580 "break;\n"
3581 "case OPTIONAL_OMIT:\n"
3582 "set_selection(OMIT_VALUE);\n"
3583 "break;\n"
3584 "default:\n"
3585 "TTCN_error(\"Assignment of an unbound optional field to a template of "
3586 "type %s.\");\n"
3587 "}\n"
3588 "return *this;\n"
3589 "}\n\n", name, name, name, name, dispname);
3590
3591 def = mputprintf(def, "%s_template& operator=(const %s_template& "
3592 "other_value);\n\n", name, name);
3593 src = mputprintf(src,
3594 "%s_template& %s_template::operator=(const %s_template& other_value)\n"
3595 "{\n"
3596 "if (&other_value != this) {\n"
3597 "clean_up();\n"
3598 "copy_template(other_value);\n"
3599 "}\n"
3600 "return *this;\n"
3601 "}\n\n", name, name, name);
3602
3603 /* indexing operators */
3604 /* Non-const operator[] is allowed to extend */
3605 def = mputprintf(def, "%s_template& operator[](int index_value);\n", type);
3606 src = mputprintf(src,
3607 "%s_template& %s_template::operator[](int index_value)\n"
3608 "{\n"
3609 "if (index_value < 0) TTCN_error(\"Accessing an element of a template "
3610 "for type %s using a negative index: %%d.\", index_value);\n"
3611 "switch (template_selection)\n"
3612 "{\n"
3613 " case SPECIFIC_VALUE:\n"
3614 " if(index_value < single_value.n_elements) break;\n"
3615 " // no break\n"
3616 " case OMIT_VALUE:\n"
3617 " case ANY_VALUE:\n"
3618 " case ANY_OR_OMIT:\n"
3619 " case UNINITIALIZED_TEMPLATE:\n"
3620 " set_size(index_value + 1);\n"
3621 " break;\n"
3622 " default:\n"
3623 " TTCN_error(\"Accessing an "
3624 "element of a non-specific template for type %s.\");\n"
3625 " break;\n"
3626 "}\n"
3627 "return *single_value.value_elements[index_value];\n"
3628 "}\n\n", type, name, dispname, dispname);
3629
3630 def = mputprintf(def, "%s_template& operator[](const INTEGER& "
3631 "index_value);\n", type);
3632 src = mputprintf(src,
3633 "%s_template& %s_template::operator[](const INTEGER& index_value)\n"
3634 "{\n"
3635 "index_value.must_bound(\"Using an unbound integer value for indexing "
3636 "a template of type %s.\");\n"
3637 "return (*this)[(int)index_value];\n"
3638 "}\n\n", type, name, dispname);
3639
3640 /* Const operator[] throws an error if over-indexing */
3641 def = mputprintf(def, "const %s_template& operator[](int index_value) "
3642 "const;\n", type);
3643 src = mputprintf(src,
3644 "const %s_template& %s_template::operator[](int index_value) const\n"
3645 "{\n"
3646 "if (index_value < 0) TTCN_error(\"Accessing an element of a template "
3647 "for type %s using a negative index: %%d.\", index_value);\n"
3648 "if (template_selection != SPECIFIC_VALUE) TTCN_error(\"Accessing an "
3649 "element of a non-specific template for type %s.\");\n"
3650 "if (index_value >= single_value.n_elements) "
3651 "TTCN_error(\"Index overflow in a template of type %s: "
3652 "The index is %%d, but the template has only %%d elements.\", "
3653 "index_value, single_value.n_elements);\n"
3654 "return *single_value.value_elements[index_value];\n"
3655 "}\n\n", type, name, dispname, dispname, dispname);
3656
3657 def = mputprintf(def, "const %s_template& operator[](const INTEGER& "
3658 "index_value) const;\n\n", type);
3659 src = mputprintf(src,
3660 "const %s_template& %s_template::operator[](const INTEGER& index_value) "
3661 "const\n"
3662 "{\n"
3663 "index_value.must_bound(\"Using an unbound integer value for indexing "
3664 "a template of type %s.\");\n"
3665 "return (*this)[(int)index_value];\n"
3666 "}\n\n", type, name, dispname);
3667
3668 /* set_size function */
3669 def = mputstr(def, "void set_size(int new_size);\n");
3670 src = mputprintf(src, "void %s_template::set_size(int new_size)\n"
3671 "{\n"
3672 "if (new_size < 0) TTCN_error(\"Internal error: Setting a negative size "
3673 "for a template of type %s.\");\n"
3674 "template_sel old_selection = template_selection;\n"
3675 "if (old_selection != SPECIFIC_VALUE) {\n"
3676 "clean_up();\n"
3677 "set_selection(SPECIFIC_VALUE);\n"
3678 "single_value.n_elements = 0;\n"
3679 "single_value.value_elements = NULL;\n"
3680 "}\n"
3681 "if (new_size > single_value.n_elements) {\n"
3682 "single_value.value_elements = (%s_template**)reallocate_pointers((void**)"
3683 "single_value.value_elements, single_value.n_elements, new_size);\n"
3684 "if (old_selection == ANY_VALUE || old_selection == ANY_OR_OMIT) {\n"
3685 "for (int elem_count = single_value.n_elements; elem_count < new_size; "
3686 "elem_count++)\n"
3687 "single_value.value_elements[elem_count] = new %s_template(ANY_VALUE);\n"
3688 "} else {\n"
3689 "for (int elem_count = single_value.n_elements; elem_count < new_size; "
3690 "elem_count++)\n"
3691 "single_value.value_elements[elem_count] = new %s_template;\n"
3692 "}\n"
3693 "single_value.n_elements = new_size;\n"
3694 "} else if (new_size < single_value.n_elements) {\n"
3695 "for (int elem_count = new_size; elem_count < single_value.n_elements; "
3696 "elem_count++)\n"
3697 "delete single_value.value_elements[elem_count];\n"
3698 "single_value.value_elements = (%s_template**)reallocate_pointers((void**)"
3699 "single_value.value_elements, single_value.n_elements, new_size);\n"
3700 "single_value.n_elements = new_size;\n"
3701 "}\n"
3702 "}\n\n", name, dispname, type, type, type, type);
3703
3704 /* raw length */
3705 def = mputstr(def, "int n_elem() const;\n");
3706 src = mputprintf(src,
3707 "int %s_template::n_elem() const\n"
3708 "{\n"
3709 " switch (template_selection) {\n"
3710 " case SPECIFIC_VALUE:\n"
3711 " return single_value.n_elements;\n"
3712 " break;\n"
3713 " case VALUE_LIST:\n"
3714 " return value_list.n_values;\n"
3715 " break;\n", name);
3716/* if (sdef->kind == SET_OF) {
3717 src = mputprintf(src,
3718 );
3719 }*/
3720 src = mputstr(src, " default:\n"
3721 " TTCN_error(\"Performing n_elem\");\n"
3722 " }\n"
3723 "}\n\n"
3724 );
3725
3726 /* sizeof operation */
3727 def = mputstr(def,
3728 "int size_of(boolean is_size) const;\n"
3729 "inline int size_of() const { return size_of(TRUE); }\n"
3730 "inline int lengthof() const { return size_of(FALSE); }\n"
3731 );
3732 src = mputprintf(src,
3733 "int %s_template::size_of(boolean is_size) const\n"
3734 "{\n"
3735 "const char* op_name = is_size ? \"size\" : \"length\";\n"
3736 "int min_size;\n"
3737 "boolean has_any_or_none;\n"
3738 "if (is_ifpresent) TTCN_error(\"Performing %%sof() operation on a "
3739 "template of type %s which has an ifpresent attribute.\", op_name);\n"
3740 "switch (template_selection)\n"
3741 "{\n"
3742 "case SPECIFIC_VALUE: {\n"
3743 " min_size = 0;\n"
3744 " has_any_or_none = FALSE;\n"
3745 " int elem_count = single_value.n_elements;\n"
3746 " if (!is_size) { while (elem_count>0 && !single_value.value_elements"
3747 "[elem_count-1]->is_bound()) elem_count--; }\n"
3748 " for (int i=0; i<elem_count; i++) {\n"
3749 " switch (single_value.value_elements[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"
3755 " break;\n"
3756 " default:\n"
3757 " min_size++;\n"
3758 " break;\n"
3759 " }\n"
3760 " }\n"
3761 "} break;\n",
3762 name, dispname, dispname);
3763 if (sdef->kind == SET_OF) {
3764 src = mputprintf(src,
3765 "case SUPERSET_MATCH:\n"
3766 "case SUBSET_MATCH: {\n"
3767 " min_size = 0;\n"
3768 " has_any_or_none = FALSE;\n"
3769 " int elem_count = value_set.n_items;\n"
3770 " if (!is_size) { while (elem_count>0 && !value_set.set_items"
3771 "[elem_count-1].is_bound()) elem_count--; }\n"
3772 " for (int i=0; i<elem_count; i++) {\n"
3773 " switch (value_set.set_items[i].get_selection())\n"
3774 " {\n"
3775 " case OMIT_VALUE:\n"
3776 " TTCN_error(\"Performing %%sof() operation on a template of type "
3777 "%s containing omit element.\", op_name);\n"
3778 " case ANY_OR_OMIT:\n"
3779 " has_any_or_none = TRUE;\n"
3780 " break;\n"
3781 " default:\n"
3782 " min_size++;\n"
3783 " break;\n"
3784 " }\n"
3785 " }\n"
3786 " if (template_selection==SUPERSET_MATCH) {\n"
3787 " has_any_or_none = TRUE;\n"
3788 " } else {\n"
3789 " int max_size = min_size;\n"
3790 " min_size = 0;\n"
3791 " if (!has_any_or_none) { // [0,max_size]\n"
3792 " switch (length_restriction_type) {\n"
3793 " case NO_LENGTH_RESTRICTION:\n"
3794 " if (max_size==0) return 0;\n"
3795 " TTCN_error(\"Performing %%sof() operation on a template of "
3796 "type %s with no exact size.\", op_name);\n"
3797 " case SINGLE_LENGTH_RESTRICTION:\n"
3798 " if (length_restriction.single_length<=max_size)\n"
3799 " return length_restriction.single_length;\n"
3800 " TTCN_error(\"Performing %%sof() operation on an invalid "
3801 "template of type %s. The maximum size (%%d) contradicts the length "
3802 "restriction (%%d).\", op_name, max_size, "
3803 "length_restriction.single_length);\n"
3804 " case RANGE_LENGTH_RESTRICTION:\n"
3805 " if (max_size==length_restriction.range_length.min_length) {\n"
3806 " return max_size;\n"
3807 " } else if (max_size>length_restriction.range_length.min_length)"
3808 "{\n"
3809 " TTCN_error(\"Performing %%sof() operation on a template of "
3810 "type %s with no exact size.\", op_name);\n"
3811 " } else\n"
3812 " TTCN_error(\"Performing %%sof() operation on an invalid "
3813 "template of type %s. Maximum size (%%d) contradicts the length "
3814 "restriction (%%d..%%d).\", op_name, max_size, "
3815 "length_restriction.range_length.min_length, "
3816 "length_restriction.range_length.max_length);\n"
3817 " default:\n"
3818 " TTCN_error(\"Internal error: Template has invalid length "
3819 "restriction type.\");\n"
3820 " }\n"
3821 " }\n"
3822 " }\n"
3823 "} break;\n",
3824 dispname, dispname, dispname, dispname, dispname);
3825 } /* set of */
3826 src = mputprintf(src,
3827 "case OMIT_VALUE:\n"
3828 " TTCN_error(\"Performing %%sof() operation on a template of type %s "
3829 "containing omit value.\", op_name);\n"
3830 "case ANY_VALUE:\n"
3831 "case ANY_OR_OMIT:\n"
3832 " min_size = 0;\n"
3833 " has_any_or_none = TRUE;\n"
3834 " break;\n"
3835 "case VALUE_LIST:\n"
3836 "{\n"
3837 " if (value_list.n_values<1)\n"
3838 " TTCN_error(\"Performing %%sof() operation on a "
3839 "template of type %s containing an empty list.\", op_name);\n"
3840 " int item_size = value_list.list_value[0].size_of(is_size);\n"
3841 " for (unsigned int i = 1; i < value_list.n_values; i++) {\n"
3842 " if (value_list.list_value[i].size_of(is_size)!=item_size)\n"
3843 " TTCN_error(\"Performing %%sof() operation on a template of type "
3844 "%s containing a value list with different sizes.\", op_name);\n"
3845 " }\n"
3846 " min_size = item_size;\n"
3847 " has_any_or_none = FALSE;\n"
3848 " break;\n"
3849 "}\n"
3850 "case COMPLEMENTED_LIST:\n"
3851 " TTCN_error(\"Performing %%sof() operation on a template of type %s "
3852 "containing complemented list.\", op_name);\n"
3853 "default:\n"
3854 " TTCN_error(\"Performing %%sof() operation on an "
3855 "uninitialized/unsupported template of type %s.\", op_name);\n"
3856 "}\n"
3857 "return check_section_is_single(min_size, has_any_or_none, "
3858 "op_name, \"a\", \"template of type %s\");\n"
3859 "}\n\n",
3860 dispname, dispname, dispname, dispname, dispname, dispname);
3861
3862 /* match operation */
3863 def = mputprintf(def, "boolean match(const %s& other_value) const;\n",
3864 name);
3865 src = mputprintf(src,
3866 "boolean %s_template::match(const %s& other_value) const\n"
3867 "{\n"
3868 "if (!other_value.is_bound()) return FALSE;\n"
3869 "int value_length = other_value.size_of();\n"
3870 "if (!match_length(value_length)) return FALSE;\n"
3871 "switch (template_selection) {\n"
3872 "case SPECIFIC_VALUE:\n"
3873 "return match_%s_of(&other_value, value_length, this, "
3874 "single_value.n_elements, match_function_specific);\n"
3875 "case OMIT_VALUE:\n"
3876 "return FALSE;\n"
3877 "case ANY_VALUE:\n"
3878 "case ANY_OR_OMIT:\n"
3879 "return TRUE;\n"
3880 "case VALUE_LIST:\n"
3881 "case COMPLEMENTED_LIST:\n"
3882 "for (unsigned int list_count = 0; list_count < value_list.n_values; "
3883 "list_count++)\n"
3884 "if (value_list.list_value[list_count].match(other_value)) "
3885 "return template_selection == VALUE_LIST;\n"
3886 "return template_selection == COMPLEMENTED_LIST;\n",
3887 name, name, sdef->kind == RECORD_OF ? "record" : "set");
3888 if (sdef->kind == SET_OF) {
3889 src = mputstr(src,
3890 "case SUPERSET_MATCH:\n"
3891 "case SUBSET_MATCH:\n"
3892 "return match_set_of(&other_value, value_length, this, "
3893 "value_set.n_items, match_function_set);\n");
3894 }
3895 src = mputprintf(src,
3896 "default:\n"
3897 "TTCN_error(\"Matching with an uninitialized/unsupported template "
3898 "of type %s.\");\n"
3899 "}\n"
3900 "return FALSE;\n"
3901 "}\n\n", dispname);
3902
3903 /* is_bound function */
3904 def = mputstr(def,
3905 "inline boolean is_bound() const \n"
3906 " {return template_selection != UNINITIALIZED_TEMPLATE; }\n");
3907
3908 /* is_value operation */
3909 def = mputstr(def, "boolean is_value() const;\n");
3910 src = mputprintf(src,
3911 "boolean %s_template::is_value() const\n"
3912 "{\n"
3913 "if (template_selection != SPECIFIC_VALUE || is_ifpresent) return false;\n"
3914 "for (int elem_count = 0; elem_count < single_value.n_elements; "
3915 "elem_count++)\n"
3916 "if (!single_value.value_elements[elem_count]->is_value()) return false;\n"
3917 "return true;\n"
3918 "}\n\n", name);
3919
3920 /* valueof operation */
3921 def = mputprintf(def, "%s valueof() const;\n", name);
3922 src = mputprintf(src,
3923 "%s %s_template::valueof() const\n"
3924 "{\n"
3925 "if (template_selection != SPECIFIC_VALUE || is_ifpresent) TTCN_error(\""
3926 "Performing a valueof or send operation on a non-specific template of type "
3927 "%s.\");\n"
3928 "%s ret_val;\n"
3929 "ret_val.set_size(single_value.n_elements);\n"
3930 "for (int elem_count = 0; elem_count < single_value.n_elements; "
3931 "elem_count++)\n"
3932 "if (single_value.value_elements[elem_count]->is_bound()) {\n"
3933 "ret_val[elem_count] = single_value.value_elements[elem_count]->valueof();\n"
3934 "}\n"
3935 "return ret_val;\n"
3936 "}\n\n", name, name, dispname, name);
3937
3938 /* substr() predefined function for templates */
3939 def = mputprintf(def,
3940 "%s substr(int index, int returncount) const;\n\n", name);
3941 src = mputprintf(src,
3942 "%s %s_template::substr(int index, int returncount) const\n"
3943 "{\n"
3944 "if (!is_value()) TTCN_error(\"The first argument of function substr() is "
3945 "a template with non-specific value.\");\n"
3946 "return valueof().substr(index, returncount);\n"
3947 "}\n\n", name, name);
3948
3949 /* replace() predefined function for templates */
3950 def = mputprintf(def,
3951 "%s replace(int index, int len, const %s_template& repl) const;\n\n", name, name);
3952 src = mputprintf(src,
3953 "%s %s_template::replace(int index, int len, const %s_template& repl) const\n"
3954 "{\n"
3955 "if (!is_value()) TTCN_error(\"The first argument of function replace() is "
3956 "a template with non-specific value.\");\n"
3957 "if (!repl.is_value()) TTCN_error(\"The fourth argument of function "
3958 "replace() is a template with non-specific value.\");\n"
3959 "return valueof().replace(index, len, repl.valueof());\n"
3960 "}\n\n", name, name, name);
3961 def = mputprintf(def,
3962 "%s replace(int index, int len, const %s& repl) const;\n\n", name, name);
3963 src = mputprintf(src,
3964 "%s %s_template::replace(int index, int len, const %s& repl) const\n"
3965 "{\n"
3966 "if (!is_value()) TTCN_error(\"The first argument of function replace() is "
3967 "a template with non-specific value.\");\n"
3968 "return valueof().replace(index, len, repl);\n"
3969 "}\n\n", name, name, name);
3970
3971 /* value list and set handling operators */
3972 def = mputstr(def,
3973 "void set_type(template_sel template_type, unsigned int list_length);\n");
3974 src = mputprintf(src,
3975 "void %s_template::set_type(template_sel template_type, "
3976 "unsigned int list_length)\n"
3977 "{\n"
3978 "clean_up();\n"
3979 "switch (template_type) {\n"
3980 "case VALUE_LIST:\n"
3981 "case COMPLEMENTED_LIST:\n"
3982 "value_list.n_values = list_length;\n"
3983 "value_list.list_value = new %s_template[list_length];\n"
3984 "break;\n", name, name);
3985 if (sdef->kind == SET_OF) {
3986 src = mputprintf(src,
3987 "case SUPERSET_MATCH:\n"
3988 "case SUBSET_MATCH:\n"
3989 "value_set.n_items = list_length;\n"
3990 "value_set.set_items = new %s_template[list_length];\n"
3991 "break;\n", type);
3992 }
3993 src = mputprintf(src,
3994 "default:\n"
3995 "TTCN_error(\"Internal error: Setting an invalid type for a template of "
3996 "type %s.\");\n"
3997 "}\n"
3998 "set_selection(template_type);\n"
3999 "}\n\n", dispname);
4000
4001 def = mputprintf(def,
4002 "%s_template& list_item(unsigned int list_index);\n", name);
4003 src = mputprintf(src,
4004 "%s_template& %s_template::list_item(unsigned int list_index)\n"
4005 "{\n"
4006 "if (template_selection != VALUE_LIST && "
4007 "template_selection != COMPLEMENTED_LIST) "
4008 "TTCN_error(\"Internal error: Accessing a list element of a non-list "
4009 "template of type %s.\");\n"
4010 "if (list_index >= value_list.n_values) "
4011 "TTCN_error(\"Internal error: Index overflow in a value list template "
4012 "of type %s.\");\n"
4013 "return value_list.list_value[list_index];\n"
4014 "}\n\n", name, name, dispname, dispname);
4015
4016 if (sdef->kind == SET_OF) {
4017 def = mputprintf(def,
4018 "%s_template& set_item(unsigned int set_index);\n", type);
4019 src = mputprintf(src,
4020 "%s_template& %s_template::set_item(unsigned int set_index)\n"
4021 "{\n"
4022 "if (template_selection != SUPERSET_MATCH && "
4023 "template_selection != SUBSET_MATCH) "
4024 "TTCN_error(\"Internal error: Accessing a set element of a non-set "
4025 "template of type %s.\");\n"
4026 "if (set_index >= value_set.n_items) "
4027 "TTCN_error(\"Internal error: Index overflow in a set template of "
4028 "type %s.\");\n"
4029 "return value_set.set_items[set_index];\n"
4030 "}\n\n", type, name, dispname, dispname);
4031 }
4032
4033 /* logging functions */
4034 def = mputstr(def, "void log() const;\n");
4035 src = mputprintf
4036 (src,
4037 "void %s_template::log() const\n"
4038 "{\n"
4039 "switch (template_selection) {\n"
4040 "case SPECIFIC_VALUE:\n"
4041 "if (single_value.n_elements > 0) {\n"
4042 "TTCN_Logger::log_event_str(\"{ \");\n"
4043 "for (int elem_count = 0; elem_count < single_value.n_elements; "
4044 "elem_count++) {\n"
4045 "if (elem_count > 0) TTCN_Logger::log_event_str(\", \");\n", name);
4046 if (sdef->kind == RECORD_OF) {
4047 src = mputstr(src,
4048 "if (permutation_starts_at(elem_count)) "
4049 "TTCN_Logger::log_event_str(\"permutation(\");\n");
4050 }
4051 src = mputstr(src, "single_value.value_elements[elem_count]->log();\n");
4052 if (sdef->kind == RECORD_OF) {
4053 src = mputstr(src,
4054 "if (permutation_ends_at(elem_count)) TTCN_Logger::log_char(')');\n");
4055 }
4056 src = mputstr(src,
4057 "}\n"
4058 "TTCN_Logger::log_event_str(\" }\");\n"
4059 "} else TTCN_Logger::log_event_str(\"{ }\");\n"
4060 "break;\n"
4061 "case COMPLEMENTED_LIST:\n"
4062 "TTCN_Logger::log_event_str(\"complement\");\n"
4063 "case VALUE_LIST:\n"
4064 "TTCN_Logger::log_char('(');\n"
4065 "for (unsigned int list_count = 0; list_count < value_list.n_values; "
4066 "list_count++) {\n"
4067 "if (list_count > 0) TTCN_Logger::log_event_str(\", \");\n"
4068 "value_list.list_value[list_count].log();\n"
4069 "}\n"
4070 "TTCN_Logger::log_char(')');\n"
4071 "break;\n");
4072 if (sdef->kind == SET_OF) {
4073 src = mputstr(src,
4074 "case SUPERSET_MATCH:\n"
4075 "case SUBSET_MATCH:\n"
4076 "TTCN_Logger::log_event(\"%s(\", template_selection == SUPERSET_MATCH "
4077 "? \"superset\" : \"subset\");\n"
4078 "for (unsigned int set_count = 0; set_count < value_set.n_items; "
4079 "set_count++) {\n"
4080 "if (set_count > 0) TTCN_Logger::log_event_str(\", \");\n"
4081 "value_set.set_items[set_count].log();\n"
4082 "}\n"
4083 "TTCN_Logger::log_char(')');\n"
4084 "break;\n");
4085 }
4086 src = mputstr(src,
4087 "default:\n"
4088 "log_generic();\n"
4089 "}\n"
4090 "log_restricted();\n"
4091 "log_ifpresent();\n"
4092 "}\n\n");
4093
4094 def = mputprintf(def, "void log_match(const %s& match_value) const;\n",
4095 name);
4096 src = mputprintf(src, "void %s_template::log_match(const %s& match_value) "
4097 "const\n"
4098 "{\n"
4099 "if(TTCN_Logger::VERBOSITY_COMPACT == TTCN_Logger::get_matching_verbosity()){\n"
4100 "if(match(match_value)){\n"
4101 "TTCN_Logger::print_logmatch_buffer();\n"
4102 "TTCN_Logger::log_event_str(\" matched\");\n"
4103 "}else{\n", name, name);
4104
4105 if (sdef->kind == RECORD_OF) {
4106 src = mputstr(src,
4107 "if (template_selection == SPECIFIC_VALUE && "
4108 "single_value.n_elements > 0 && get_number_of_permutations() == 0 && "
4109 "single_value.n_elements == match_value.size_of()) {\n"
4110 "size_t previous_size = TTCN_Logger::get_logmatch_buffer_len();\n"
4111 "for (int elem_count = 0; elem_count < single_value.n_elements; "
4112 "elem_count++) {\n"
4113 "if(!single_value.value_elements[elem_count]->match(match_value[elem_count])){\n"
4114 "TTCN_Logger::log_logmatch_info(\"[%d]\", elem_count);\n"
4115 "single_value.value_elements[elem_count]->log_match(match_value[elem_count]);\n"
4116 "TTCN_Logger::set_logmatch_buffer_len(previous_size);\n"
4117 "}\n"
4118 "}\n"
4119 "log_match_length(single_value.n_elements);\n"
4120 "} else {\n"
4121 "TTCN_Logger::print_logmatch_buffer();\n"
4122 "match_value.log();\n"
4123 "TTCN_Logger::log_event_str(\" with \");\n"
4124 "log();\n"
4125 "TTCN_Logger::log_event_str(\" unmatched\");\n"
4126 "}\n");
4127 }
4128 if (sdef->kind == SET_OF) {
4129 src = mputstr(src,
4130 "size_t previous_size = TTCN_Logger::get_logmatch_buffer_len();\n"
4131 "if (template_selection == SPECIFIC_VALUE)\n"
4132 " log_match_heuristics(&match_value, match_value.size_of(), this, "
4133 "single_value.n_elements, match_function_specific, log_function);\n"
4134 "else{\n"
4135 "if(previous_size != 0){\n"
4136 "TTCN_Logger::print_logmatch_buffer();\n"
4137 "TTCN_Logger::set_logmatch_buffer_len(previous_size);\n"
4138 "TTCN_Logger::log_event_str(\":=\");\n"
4139 "}\n"
4140 "}\n"
4141 "match_value.log();\n"
4142 "TTCN_Logger::log_event_str(\" with \");\n"
4143 "log();\n"
4144 "TTCN_Logger::log_event_str(\" unmatched\");\n"
4145 );
4146 }
4147
4148 src = mputstr(src, "}\n"
4149 "return;\n"
4150 "}\n");
4151 if (sdef->kind == RECORD_OF) {
4152 /* logging by element is meaningful for 'record of' only */
4153 src = mputstr(src,
4154 "if (template_selection == SPECIFIC_VALUE && "
4155 "single_value.n_elements > 0 && get_number_of_permutations() == 0 && "
4156 "single_value.n_elements == match_value.size_of()) {\n"
4157 "TTCN_Logger::log_event_str(\"{ \");\n"
4158 "for (int elem_count = 0; elem_count < single_value.n_elements; "
4159 "elem_count++) {\n"
4160 "if (elem_count > 0) TTCN_Logger::log_event_str(\", \");\n"
4161 "single_value.value_elements[elem_count]->log_match"
4162 "(match_value[elem_count]);\n"
4163 "}\n"
4164 "TTCN_Logger::log_event_str(\" }\");\n"
4165 "log_match_length(single_value.n_elements);\n"
4166 "} else {\n");
4167 }
4168 src = mputstr(src,
4169 "match_value.log();\n"
4170 "TTCN_Logger::log_event_str(\" with \");\n"
4171 "log();\n"
4172 "if (match(match_value)) TTCN_Logger::log_event_str(\" matched\");\n");
4173 if (sdef->kind == SET_OF) {
4174 src = mputstr(src, "else {\n"
4175 "TTCN_Logger::log_event_str(\" unmatched\");\n"
4176 "if (template_selection == SPECIFIC_VALUE) log_match_heuristics("
4177 "&match_value, match_value.size_of(), this, single_value.n_elements, "
4178 "match_function_specific, log_function);\n"
4179 "}\n");
4180 } else {
4181 src = mputstr(src, "else TTCN_Logger::log_event_str(\" unmatched\");\n"
4182 "}\n");
4183 }
4184 src = mputstr(src, "}\n\n");
4185
4186 /* encoding/decoding functions */
4187 def = mputstr(def, "void encode_text(Text_Buf& text_buf) const;\n");
4188 src = mputprintf(src,
4189 "void %s_template::encode_text(Text_Buf& text_buf) const\n"
4190 "{\n"
4191 "encode_text_%s(text_buf);\n"
4192 "switch (template_selection) {\n"
4193 "case SPECIFIC_VALUE:\n"
4194 "text_buf.push_int(single_value.n_elements);\n"
4195 "for (int elem_count = 0; elem_count < single_value.n_elements; "
4196 "elem_count++)\n"
4197 "single_value.value_elements[elem_count]->encode_text(text_buf);\n"
4198 "case OMIT_VALUE:\n"
4199 "case ANY_VALUE:\n"
4200 "case ANY_OR_OMIT:\n"
4201 "break;\n"
4202 "case VALUE_LIST:\n"
4203 "case COMPLEMENTED_LIST:\n"
4204 "text_buf.push_int(value_list.n_values);\n"
4205 "for (unsigned int list_count = 0; list_count < value_list.n_values; "
4206 "list_count++)\n"
4207 "value_list.list_value[list_count].encode_text(text_buf);\n"
4208 "break;\n", name, sdef->kind == RECORD_OF ? "permutation" : "restricted");
4209 if (sdef->kind == SET_OF) {
4210 src = mputstr(src,
4211 "case SUPERSET_MATCH:\n"
4212 "case SUBSET_MATCH:\n"
4213 "text_buf.push_int(value_set.n_items);\n"
4214 "for (unsigned int set_count = 0; set_count < value_set.n_items; "
4215 "set_count++)\n"
4216 "value_set.set_items[set_count].encode_text(text_buf);\n"
4217 "break;\n");
4218 }
4219 src = mputprintf(src,
4220 "default:\n"
4221 "TTCN_error(\"Text encoder: Encoding an uninitialized/unsupported "
4222 "template of type %s.\");\n"
4223 "}\n"
4224 "}\n\n", dispname);
4225
4226 def = mputstr(def, "void decode_text(Text_Buf& text_buf);\n");
4227 src = mputprintf(src,
4228 "void %s_template::decode_text(Text_Buf& text_buf)\n"
4229 "{\n"
4230 "clean_up();\n"
4231 "decode_text_%s(text_buf);\n"
4232 "switch (template_selection) {\n"
4233 "case SPECIFIC_VALUE:\n"
4234 "single_value.n_elements = text_buf.pull_int().get_val();\n"
4235 "if (single_value.n_elements < 0) TTCN_error(\"Text decoder: Negative "
4236 "size was received for a template of type %s.\");\n"
4237 "single_value.value_elements = "
4238 "(%s_template**)allocate_pointers(single_value.n_elements);\n"
4239 "for (int elem_count = 0; elem_count < single_value.n_elements; "
4240 "elem_count++) {\n"
4241 "single_value.value_elements[elem_count] = new %s_template;\n"
4242 "single_value.value_elements[elem_count]->decode_text(text_buf);\n"
4243 "}\n"
4244 "case OMIT_VALUE:\n"
4245 "case ANY_VALUE:\n"
4246 "case ANY_OR_OMIT:\n"
4247 "break;\n"
4248 "case VALUE_LIST:\n"
4249 "case COMPLEMENTED_LIST:\n"
4250 "value_list.n_values = text_buf.pull_int().get_val();\n"
4251 "value_list.list_value = new %s_template[value_list.n_values];\n"
4252 "for (unsigned int list_count = 0; list_count < value_list.n_values; "
4253 "list_count++)\n"
4254 "value_list.list_value[list_count].decode_text(text_buf);\n"
4255 "break;\n", name, sdef->kind == RECORD_OF ? "permutation" : "restricted",
4256 dispname, type, type, name);
4257 if (sdef->kind == SET_OF) {
4258 src = mputprintf(src,
4259 "case SUPERSET_MATCH:\n"
4260 "case SUBSET_MATCH:\n"
4261 "value_set.n_items = text_buf.pull_int().get_val();\n"
4262 "value_set.set_items = new %s_template[value_set.n_items];\n"
4263 "for (unsigned int set_count = 0; set_count < value_set.n_items; "
4264 "set_count++)\n"
4265 "value_set.set_items[set_count].decode_text(text_buf);\n"
4266 "break;\n", type);
4267 }
4268 src = mputprintf(src,
4269 "default:\n"
4270 "TTCN_error(\"Text decoder: An unknown/unsupported selection was "
4271 "received for a template of type %s.\");\n"
4272 "}\n"
4273 "}\n\n", dispname);
4274
4275 /* TTCN-3 ispresent() function */
4276 def = mputstr(def, "boolean is_present() const;\n");
4277 src = mputprintf(src,
4278 "boolean %s_template::is_present() const\n"
4279 "{\n"
4280 "if (template_selection==UNINITIALIZED_TEMPLATE) return FALSE;\n"
4281 "return !match_omit();\n"
4282 "}\n\n", name);
4283
4284 /* match_omit() */
4285 def = mputstr(def, "boolean match_omit() const;\n");
4286 src = mputprintf(src,
4287 "boolean %s_template::match_omit() const\n"
4288 "{\n"
4289 "if (is_ifpresent) return TRUE;\n"
4290 "switch (template_selection) {\n"
4291 "case OMIT_VALUE:\n"
4292 "case ANY_OR_OMIT:\n"
4293 "return TRUE;\n"
4294 "case VALUE_LIST:\n"
4295 "case COMPLEMENTED_LIST:\n"
4296 "for (unsigned int i=0; i<value_list.n_values; i++)\n"
4297 "if (value_list.list_value[i].match_omit())\n"
4298 "return template_selection==VALUE_LIST;\n"
4299 "return template_selection==COMPLEMENTED_LIST;\n"
4300 "default:\n"
4301 "return FALSE;\n"
4302 "}\n"
4303 "return FALSE;\n"
4304 "}\n\n", name);
4305
4306 /* set_param() */
4307 def = mputstr(def, "void set_param(Module_Param& param);\n");
4308 src = mputprintf(src,
4309 "void %s_template::set_param(Module_Param& param)\n"
4310 "{\n"
4311 " if (dynamic_cast<Module_Param_Name*>(param.get_id()) != NULL &&\n"
4312 " param.get_id()->next_name()) {\n"
4313 // Haven't reached the end of the module parameter name
4314 // => the name refers to one of the elements, not to the whole record of
4315 " char* param_field = param.get_id()->get_current_name();\n"
4316 " if (param_field[0] < '0' || param_field[0] > '9') {\n"
4317 " param.error(\"Unexpected record field name in module parameter, expected a valid\"\n"
4318 " \" index for %s template type `%s'\");\n"
4319 " }\n"
4320 " int param_index = -1;\n"
4321 " sscanf(param_field, \"%%d\", &param_index);\n"
4322 " (*this)[param_index].set_param(param);\n"
4323 " return;\n"
4324 " }\n"
4325 " param.basic_check(Module_Param::BC_TEMPLATE|Module_Param::BC_LIST, \"%s of template\");\n"
4326 " switch (param.get_type()) {\n"
4327 " case Module_Param::MP_Omit:\n"
4328 " *this = OMIT_VALUE;\n"
4329 " break;\n"
4330 " case Module_Param::MP_Any:\n"
4331 " *this = ANY_VALUE;\n"
4332 " break;\n"
4333 " case Module_Param::MP_AnyOrNone:\n"
4334 " *this = ANY_OR_OMIT;\n"
4335 " break;\n"
4336 " case Module_Param::MP_List_Template:\n"
4337 " case Module_Param::MP_ComplementList_Template:\n"
4338 " set_type(param.get_type()==Module_Param::MP_List_Template ? VALUE_LIST : COMPLEMENTED_LIST, param.get_size());\n"
4339 " for (size_t p_i=0; p_i<param.get_size(); p_i++) {\n"
4340 " list_item(p_i).set_param(*param.get_elem(p_i));\n"
4341 " }\n"
4342 " break;\n"
4343 " case Module_Param::MP_Indexed_List:\n"
4344 " if (template_selection!=SPECIFIC_VALUE) set_size(0);\n"
4345 " for (size_t p_i=0; p_i<param.get_size(); ++p_i) {\n"
4346 " (*this)[(int)(param.get_elem(p_i)->get_id()->get_index())].set_param(*param.get_elem(p_i));\n"
4347 " }\n"
4348 " break;\n",
4349 name, sdef->kind==RECORD_OF?"record":"set", dispname, sdef->kind==RECORD_OF?"record":"set");
4350 if (sdef->kind == RECORD_OF) {
4351 src = mputstr(src,
4352 " case Module_Param::MP_Value_List: {\n"
4353 " set_size(param.get_size());\n"
4354 " int curr_idx = 0;\n"
4355 " for (size_t p_i=0; p_i<param.get_size(); ++p_i) {\n"
4356 " switch (param.get_elem(p_i)->get_type()) {\n"
4357 " case Module_Param::MP_NotUsed:\n"
4358 " curr_idx++;\n"
4359 " break;\n"
4360 " case Module_Param::MP_Permutation_Template: {\n"
4361 " int perm_start_idx = curr_idx;\n"
4362 " for (size_t perm_i=0; perm_i<param.get_elem(p_i)->get_size(); perm_i++) {\n"
4363 " (*this)[curr_idx].set_param(*(param.get_elem(p_i)->get_elem(perm_i)));\n"
4364 " curr_idx++;\n"
4365 " }\n"
4366 " int perm_end_idx = curr_idx - 1;\n"
4367 " add_permutation(perm_start_idx, perm_end_idx);\n"
4368 " } break;\n"
4369 " default:\n"
4370 " (*this)[curr_idx].set_param(*param.get_elem(p_i));\n"
4371 " curr_idx++;\n"
4372 " }\n"
4373 " }\n"
4374 " } break;\n");
4375 } else {
4376 src = mputstr(src,
4377 " case Module_Param::MP_Value_List:\n"
4378 " set_size(param.get_size());\n"
4379 " for (size_t p_i=0; p_i<param.get_size(); ++p_i) {\n"
4380 " if (param.get_elem(p_i)->get_type()!=Module_Param::MP_NotUsed) {\n"
4381 " (*this)[p_i].set_param(*param.get_elem(p_i));\n"
4382 " }\n"
4383 " }\n"
4384 " break;\n"
4385 " case Module_Param::MP_Superset_Template:\n"
4386 " case Module_Param::MP_Subset_Template:\n"
4387 " set_type(param.get_type()==Module_Param::MP_Superset_Template ? SUPERSET_MATCH : SUBSET_MATCH, param.get_size());\n"
4388 " for (size_t p_i=0; p_i<param.get_size(); p_i++) {\n"
4389 " set_item(p_i).set_param(*param.get_elem(p_i));\n"
4390 " }\n"
4391 " break;\n");
4392 }
4393 src = mputprintf(src,
4394 " default:\n"
4395 " param.type_error(\"%s of template\", \"%s\");\n"
4396 " }\n"
4397 " is_ifpresent = param.get_ifpresent();\n"
4398 " set_length_range(param);\n"
4399 "}\n\n", sdef->kind==RECORD_OF?"record":"set", dispname);
4400
4401 /* check template restriction */
4402 def = mputstr(def, "void check_restriction(template_res t_res, "
4403 "const char* t_name=NULL) const;\n");
4404 src = mputprintf(src,
4405 "void %s_template::check_restriction("
4406 "template_res t_res, const char* t_name) const\n"
4407 "{\n"
4408 "if (template_selection==UNINITIALIZED_TEMPLATE) return;\n"
4409 "switch ((t_name&&(t_res==TR_VALUE))?TR_OMIT:t_res) {\n"
4410 "case TR_OMIT:\n"
4411 "if (template_selection==OMIT_VALUE) return;\n"
4412 "case TR_VALUE:\n"
4413 "if (template_selection!=SPECIFIC_VALUE || is_ifpresent) break;\n"
4414 "for (int i=0; i<single_value.n_elements; i++) "
4415 "single_value.value_elements[i]->check_restriction("
4416 "t_res, t_name ? t_name : \"%s\");\n"
4417 "return;\n"
4418 "case TR_PRESENT:\n"
4419 "if (!match_omit()) return;\n"
4420 "break;\n"
4421 "default:\n"
4422 "return;\n"
4423 "}\n"
4424 "TTCN_error(\"Restriction `%%s' on template of type %%s "
4425 "violated.\", get_res_name(t_res), t_name ? t_name : \"%s\");\n"
4426 "}\n\n", name, dispname, dispname);
4427
4428 /* end of class */
4429 def = mputstr(def, "};\n\n");
4430
4431 output->header.class_decls = mputprintf(output->header.class_decls,
4432 "class %s_template;\n", name);
4433 output->header.class_defs = mputstr(output->header.class_defs, def);
4434 Free(def);
4435 output->source.methods = mputstr(output->source.methods, src);
4436 Free(src);
4437}
4438
4439/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
4440
4441void defRecordOfTemplate2(const struct_of_def *sdef, output_struct *output)
4442{
4443 char *def = NULL, *src = NULL;
4444 const char *name = sdef->name;
4445 const char *type = sdef->type;
4446 const char *base_class = sdef->kind == RECORD_OF ? "Record_Of_Template" : "Set_Of_Template";
4447
4448 /* Class definition */
4449 def = mputprintf(def, "class %s_template : public %s {\n", name, base_class);
4450
4451 /* public member functions */
4452 def = mputstr(def, "\npublic:\n");
4453
4454 /* constructors */
4455 def = mputprintf(def, "%s_template() {}\n", name);
4456
4457 def = mputprintf(def, "%s_template(template_sel other_value): %s(other_value) "
4458 "{ check_single_selection(other_value); }\n", name, base_class);
4459
4460 def = mputprintf(def, "%s_template(null_type other_value);\n", name);
4461 src = mputprintf(src, "%s_template::%s_template(null_type)\n"
4462 " : %s(SPECIFIC_VALUE)\n"
4463 "{\n"
4464 "single_value.n_elements = 0;\n"
4465 "single_value.value_elements = NULL;\n"
4466 "}\n\n", name, name, base_class);
4467
4468 def = mputprintf(def, "%s_template(const %s& other_value) "
4469 "{ copy_value(&other_value); }\n", name, name);
4470 def = mputprintf(def, "%s_template(const OPTIONAL<%s>& other_value) "
4471 "{ copy_optional(&other_value); }\n", name, name);
4472
4473 /* copy constructor */
4474 def = mputprintf(def, "%s_template(const %s_template& other_value): %s() { copy_template(other_value); }\n",
4475 name, name, base_class);
4476
4477 /* assignment operators */
4478 def = mputprintf(def, "%s_template& operator=(template_sel other_value);\n",
4479 name);
4480 src = mputprintf(src,
4481 "%s_template& %s_template::operator=(template_sel other_value)\n"
4482 "{\n"
4483 "check_single_selection(other_value);\n"
4484 "clean_up();\n"
4485 "set_selection(other_value);\n"
4486 "return *this;\n"
4487 "}\n\n", name, name);
4488
4489 def = mputprintf(def, "%s_template& operator=(null_type other_value);\n",
4490 name);
4491 src = mputprintf(src,
4492 "%s_template& %s_template::operator=(null_type)\n"
4493 "{\n"
4494 "clean_up();\n"
4495 "set_selection(SPECIFIC_VALUE);\n"
4496 "single_value.n_elements = 0;\n"
4497 "single_value.value_elements = NULL;\n"
4498 "return *this;\n"
4499 "}\n\n", name, name);
4500
4501 def = mputprintf(def, "%s_template& operator=(const %s& other_value);\n",
4502 name, name);
4503 src = mputprintf(src,
4504 "%s_template& %s_template::operator=(const %s& other_value)\n"
4505 "{\n"
4506 "clean_up();\n"
4507 "copy_value(&other_value);\n"
4508 "return *this;\n"
4509 "}\n\n", name, name, name);
4510
4511 def = mputprintf(def, "%s_template& operator=(const OPTIONAL<%s>& "
4512 "other_value);\n", name, name);
4513 src = mputprintf(src,
4514 "%s_template& %s_template::operator=(const OPTIONAL<%s>& other_value)\n"
4515 "{\n"
4516 "clean_up();\n"
4517 "copy_optional(&other_value);\n"
4518 "return *this;\n"
4519 "}\n\n", name, name, name);
4520
4521 def = mputprintf(def, "%s_template& operator=(const %s_template& "
4522 "other_value);\n\n", name, name);
4523 src = mputprintf(src,
4524 "%s_template& %s_template::operator=(const %s_template& other_value)\n"
4525 "{\n"
4526 "if (&other_value != this) {\n"
4527 "clean_up();\n"
4528 "copy_template(other_value);\n"
4529 "}\n"
4530 "return *this;\n"
4531 "}\n\n", name, name, name);
4532
4533 /* indexing operators */
4534 def = mputprintf(def,
4535 "%s_template& operator[](int index_value);\n"
4536 "%s_template& operator[](const INTEGER& index_value);\n"
4537 "const %s_template& operator[](int index_value) const;\n"
4538 "const %s_template& operator[](const INTEGER& index_value) const;\n",
4539 type,
4540 type,
4541 type,
4542 type);
4543
4544 src = mputprintf(src,
4545 "%s_template& %s_template::operator[](int index_value) { return *(static_cast<%s_template*>(get_at(index_value))); }\n"
4546 "%s_template& %s_template::operator[](const INTEGER& index_value) { return *(static_cast<%s_template*>(get_at(index_value))); }\n"
4547 "const %s_template& %s_template::operator[](int index_value) const { return *(static_cast<const %s_template*>(get_at(index_value))); }\n"
4548 "const %s_template& %s_template::operator[](const INTEGER& index_value) const { return *(static_cast<const %s_template*>(get_at(index_value))); }\n\n",
4549 type, name, type,
4550 type, name, type,
4551 type, name, type,
4552 type, name, type);
4553
4554 /* match operation */
4555 def = mputprintf(def, "inline boolean match(const %s& match_value) const "
4556 "{ return matchv(&match_value); }\n", name);
4557
4558 /* valueof operation */
4559 def = mputprintf(def, "%s valueof() const;\n", name);
4560 src = mputprintf(src,
4561 "%s %s_template::valueof() const\n"
4562 "{\n"
4563 "%s ret_val;\n"
4564 "valueofv(&ret_val);\n"
4565 "return ret_val;\n"
4566 "}\n\n", name, name, name);
4567
4568 /* substr() predefined function for templates */
4569 def = mputprintf(def,
4570 "%s substr(int index, int returncount) const;\n\n", name);
4571 src = mputprintf(src,
4572 "%s %s_template::substr(int index, int returncount) const\n"
4573 "{\n"
4574 "%s rec_of;\n"
4575 "substr_(index, returncount, &rec_of);\n"
4576 "return rec_of;\n"
4577 "}\n\n", name, name, name);
4578
4579 /* replace() predefined function for templates */
4580 def = mputprintf(def,
4581 "%s replace(int index, int len, const %s_template& repl) const;\n\n",
4582 name, name);
4583 src = mputprintf(src,
4584 "%s %s_template::replace(int index, int len, const %s_template& repl) const\n"
4585 "{\n"
4586 "%s rec_of;\n"
4587 "replace_(index, len, &repl, &rec_of);\n"
4588 "return rec_of;\n"
4589 "}\n\n", name, name, name, name);
4590 def = mputprintf(def,
4591 "%s replace(int index, int len, const %s& repl) const;\n\n",
4592 name, name);
4593 src = mputprintf(src,
4594 "%s %s_template::replace(int index, int len, const %s& repl) const\n"
4595 "{\n"
4596 "%s rec_of;\n"
4597 "replace_(index, len, &repl, &rec_of);\n"
4598 "return rec_of;\n"
4599 "}\n\n", name, name, name, name);
4600
4601 /* value list and set handling operators */
4602 def = mputprintf(def,
4603 "inline %s_template& list_item(int list_index) { return *(static_cast<%s_template*>(get_list_item(list_index))); }\n", name, name);
4604
4605 if (sdef->kind == SET_OF) {
4606 def = mputprintf(def, "%s_template& set_item(int set_index);\n", type);
4607 src = mputprintf(src,
4608 "%s_template& %s_template::set_item(int set_index) "
4609 "{ return *(static_cast<%s_template*>(get_set_item(set_index))); }\n",
4610 type, name, type);
4611 }
4612
4613 /* logging functions */
4614 def = mputprintf(def, "inline void log_match(const %s& match_value) const "
4615 "{ log_matchv(&match_value); }\n", name);
4616
4617 /* virtual helper functions */
4618 def = mputprintf(def,
4619 "%s* create() const { return new %s_template; }\n"
4620 "Base_Template* create_elem() const;\n"
4621 "const TTCN_Typedescriptor_t* get_descriptor() const;\n",
4622 base_class, name);
4623 src = mputprintf(src,
4624 "Base_Template* %s_template::create_elem() const { return new %s_template; }\n"
4625 "const TTCN_Typedescriptor_t* %s_template::get_descriptor() const { return &%s_descr_; }\n",
4626 name, type,
4627 name, name);
4628
4629 /* end of class */
4630 def = mputstr(def, "};\n\n");
4631
4632 output->header.class_decls = mputprintf(output->header.class_decls,
4633 "class %s_template;\n", name);
4634 output->header.class_defs = mputstr(output->header.class_defs, def);
4635 Free(def);
4636 output->source.methods = mputstr(output->source.methods, src);
4637 Free(src);
4638}
This page took 0.230823 seconds and 5 git commands to generate.