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