Commit | Line | Data |
---|---|---|
d44e3c4f | 1 | /****************************************************************************** |
2 | * Copyright (c) 2000-2016 Ericsson Telecom AB | |
3 | * All rights reserved. This program and the accompanying materials | |
4 | * are made available under the terms of the Eclipse Public License v1.0 | |
5 | * which accompanies this distribution, and is available at | |
6 | * http://www.eclipse.org/legal/epl-v10.html | |
7 | * | |
8 | * Contributors: | |
9 | * Baji, Laszlo | |
10 | * Balasko, Jeno | |
11 | * Baranyi, Botond | |
12 | * Delic, Adam | |
13 | * Forstner, Matyas | |
14 | * Kovacs, Ferenc | |
15 | * Raduly, Csaba | |
16 | * Szabados, Kristof | |
17 | * Szabo, Bence Janos | |
18 | * Szabo, Janos Zoltan – initial implementation | |
19 | * Szalai, Gabor | |
20 | * | |
21 | ******************************************************************************/ | |
970ed795 EL |
22 | #include "../common/memory.h" |
23 | #include "datatypes.h" | |
24 | #include "main.hh" | |
25 | #include "encdec.h" | |
26 | ||
27 | void def_encdec(const char *p_classname, | |
28 | char **p_classdef, char **p_classsrc, | |
29 | boolean ber, boolean raw, boolean text, boolean xer, | |
30 | boolean json, boolean is_leaf) | |
31 | { | |
32 | char *def=NULL; | |
33 | char *src=NULL; | |
34 | ||
35 | def=mputstr | |
36 | (def, | |
37 | "void encode(const TTCN_Typedescriptor_t&, TTCN_Buffer&," | |
38 | " TTCN_EncDec::coding_t, ...) const;\n" | |
39 | "void decode(const TTCN_Typedescriptor_t&, TTCN_Buffer&," | |
40 | " TTCN_EncDec::coding_t, ...);\n"); | |
41 | if(ber) | |
42 | def=mputstr(def, | |
43 | "ASN_BER_TLV_t* BER_encode_TLV(const TTCN_Typedescriptor_t& p_td," | |
44 | " unsigned p_coding) const;\n" | |
45 | "boolean BER_decode_TLV(const TTCN_Typedescriptor_t& p_td, const" | |
46 | " ASN_BER_TLV_t& p_tlv, unsigned L_form);\n" | |
47 | ); | |
48 | if(raw) | |
49 | def=mputprintf(def, | |
50 | "int RAW_encode(const TTCN_Typedescriptor_t&, RAW_enc_tree&) const;\n" | |
51 | "int RAW_decode(const TTCN_Typedescriptor_t&, TTCN_Buffer&," | |
52 | " int, raw_order_t, boolean no_err=FALSE," | |
53 | "int sel_field=-1, boolean first_call=TRUE);\n" | |
54 | ); | |
55 | if(text) | |
56 | def=mputprintf(def, | |
57 | "int TEXT_encode(const TTCN_Typedescriptor_t&, TTCN_Buffer&) const;\n" | |
58 | "int TEXT_decode(const TTCN_Typedescriptor_t&," | |
59 | "TTCN_Buffer&, Limit_Token_List&, boolean no_err=FALSE," | |
60 | "boolean first_call=TRUE);\n" | |
61 | ); | |
62 | if (xer) /* XERSTUFF encdec function headers */ | |
63 | def=mputprintf(def, | |
64 | #ifndef NDEBUG | |
65 | "// written by %s in " __FILE__ " at %d\n" | |
66 | #endif | |
af710487 | 67 | "int XER_encode(const XERdescriptor_t&, TTCN_Buffer&, unsigned int, int, " |
68 | "embed_values_enc_struct_t*) const;\n" | |
69 | "int XER_decode(const XERdescriptor_t&, XmlReaderWrap&, unsigned int, " | |
feade998 | 70 | "unsigned int, embed_values_dec_struct_t*);\n" |
970ed795 EL |
71 | "static boolean can_start(const char *name, const char *uri, " |
72 | "XERdescriptor_t const& xd, unsigned int);\n" | |
73 | "%s" | |
74 | #ifndef NDEBUG | |
75 | , __FUNCTION__, __LINE__ | |
76 | #endif | |
77 | , use_runtime_2 ? | |
78 | "boolean can_start_v(const char *name, const char *uri, " | |
79 | "XERdescriptor_t const& xd, unsigned int);\n" : "" | |
80 | ); | |
81 | if(json) { | |
82 | def = mputprintf(def, | |
83 | "int JSON_encode(const TTCN_Typedescriptor_t&, JSON_Tokenizer&) const;\n" | |
84 | "int JSON_decode(const TTCN_Typedescriptor_t&, JSON_Tokenizer&, boolean);\n"); | |
85 | } | |
86 | ||
87 | src=mputprintf(src, | |
88 | "void %s::encode(const TTCN_Typedescriptor_t& p_td," | |
89 | " TTCN_Buffer& p_buf, TTCN_EncDec::coding_t p_coding, ...) const\n" | |
90 | "{\n" | |
91 | " va_list pvar;\n" | |
92 | " va_start(pvar, p_coding);\n" | |
93 | " switch(p_coding) {\n" | |
94 | " case TTCN_EncDec::CT_BER: {\n" | |
95 | " TTCN_EncDec_ErrorContext ec(\"While BER-encoding type" | |
96 | " '%%s': \", p_td.name);\n" | |
97 | " unsigned BER_coding=va_arg(pvar, unsigned);\n" | |
98 | " BER_encode_chk_coding(BER_coding);\n" | |
99 | " ASN_BER_TLV_t *tlv=BER_encode_TLV(p_td, BER_coding);\n" | |
100 | " tlv->put_in_buffer(p_buf);\n" | |
101 | " ASN_BER_TLV_t::destruct(tlv);\n" | |
102 | " break;}\n" | |
103 | " case TTCN_EncDec::CT_RAW: {\n" | |
104 | " TTCN_EncDec_ErrorContext ec(\"While RAW-encoding type" | |
105 | " '%%s': \", p_td.name);\n" | |
106 | " if(!p_td.raw)\n" | |
107 | " TTCN_EncDec_ErrorContext::error_internal\n" | |
108 | " (\"No RAW descriptor available for type '%%s'.\", p_td.name);\n" | |
109 | " RAW_enc_tr_pos rp;\n" | |
110 | " rp.level=0;\n" | |
111 | " rp.pos=NULL;\n" | |
112 | " RAW_enc_tree root(%s, NULL, &rp, 1, p_td.raw);\n" | |
113 | " RAW_encode(p_td, root);\n" | |
114 | " root.put_to_buf(p_buf);\n" | |
115 | " break;}\n" | |
116 | " case TTCN_EncDec::CT_TEXT: {\n" | |
117 | " TTCN_EncDec_ErrorContext ec(" | |
118 | "\"While TEXT-encoding type '%%s': \", p_td.name);\n" | |
119 | " if(!p_td.text)\n" | |
120 | " TTCN_EncDec_ErrorContext::error_internal\n" | |
121 | " (\"No TEXT descriptor available for type '%%s'.\", p_td.name);\n" | |
122 | " TEXT_encode(p_td,p_buf);\n" | |
123 | " break;}\n" | |
124 | /* XERSTUFF encoder */ | |
125 | " case TTCN_EncDec::CT_XER: {\n" | |
126 | " TTCN_EncDec_ErrorContext ec(" | |
127 | "\"While XER-encoding type '%%s': \", p_td.name);\n" | |
128 | " unsigned XER_coding=va_arg(pvar, unsigned);\n" | |
129 | " XER_encode_chk_coding(XER_coding, p_td);\n" | |
130 | /* Do not use %s_xer_ here. It supplies the XER descriptor of oldtype | |
131 | * even if encoding newtype for: | |
132 | * <ttcn>type newtype oldtype;</ttcn> */ | |
af710487 | 133 | " XER_encode(*(p_td.xer),p_buf, XER_coding, 0, 0);\n" |
970ed795 EL |
134 | " p_buf.put_c('\\n');\n" /* make sure it has a newline */ |
135 | " break;}\n" | |
136 | " case TTCN_EncDec::CT_JSON: {\n" | |
137 | " TTCN_EncDec_ErrorContext ec(" | |
138 | "\"While JSON-encoding type '%%s': \", p_td.name);\n" | |
139 | " if(!p_td.json)\n" | |
140 | " TTCN_EncDec_ErrorContext::error_internal\n" | |
141 | " (\"No JSON descriptor available for type '%%s'.\", p_td.name);\n" | |
142 | " JSON_Tokenizer tok(va_arg(pvar, int) != 0);\n" | |
143 | " JSON_encode(p_td, tok);\n" | |
144 | " p_buf.put_s(tok.get_buffer_length(), (const unsigned char*)tok.get_buffer());\n" | |
145 | " break;}\n" | |
146 | " default:\n" | |
147 | " TTCN_error(\"Unknown coding method requested to encode" | |
148 | " type '%%s'\", p_td.name);\n" | |
149 | " }\n" | |
150 | " va_end(pvar);\n" | |
151 | "}\n" | |
152 | "\n" | |
153 | , p_classname, is_leaf?"TRUE":"FALSE" | |
154 | ); | |
155 | ||
156 | src=mputprintf(src, | |
157 | #ifndef NDEBUG | |
158 | "// written by %s in " __FILE__ " at %d\n" | |
159 | #endif | |
160 | "void %s::decode(const TTCN_Typedescriptor_t& p_td," | |
161 | " TTCN_Buffer& p_buf, TTCN_EncDec::coding_t p_coding, ...)\n" | |
162 | "{\n" | |
163 | " va_list pvar;\n" | |
164 | " va_start(pvar, p_coding);\n" | |
165 | " switch(p_coding) {\n" | |
166 | " case TTCN_EncDec::CT_BER: {\n" | |
167 | " TTCN_EncDec_ErrorContext ec(\"While BER-decoding type" | |
168 | " '%%s': \", p_td.name);\n" | |
169 | " unsigned L_form=va_arg(pvar, unsigned);\n" | |
170 | " ASN_BER_TLV_t tlv;\n" | |
171 | " BER_decode_str2TLV(p_buf, tlv, L_form);\n" | |
172 | " BER_decode_TLV(p_td, tlv, L_form);\n" | |
173 | " if(tlv.isComplete) p_buf.increase_pos(tlv.get_len());\n" | |
174 | " break;}\n" | |
175 | " case TTCN_EncDec::CT_RAW: {\n" | |
176 | " TTCN_EncDec_ErrorContext ec(\"While RAW-decoding" | |
177 | " type '%%s': \", p_td.name);\n" | |
178 | " if(!p_td.raw)\n" | |
179 | " TTCN_EncDec_ErrorContext::error_internal\n" | |
180 | " (\"No RAW descriptor available for type '%%s'.\", p_td.name);\n" | |
181 | " raw_order_t r_order;\n" | |
182 | " switch(p_td.raw->top_bit_order) {\n" | |
183 | " case TOP_BIT_LEFT:\n" | |
184 | " r_order=ORDER_LSB;\n" | |
185 | " break;\n" | |
186 | " case TOP_BIT_RIGHT:\n" | |
187 | " default:\n" | |
188 | " r_order=ORDER_MSB;\n" | |
189 | " }\n" | |
190 | " int rawr = RAW_decode(p_td, p_buf, p_buf.get_len()*8, r_order);\n" | |
191 | " if(rawr<0) switch (-rawr) {\n" | |
192 | " case TTCN_EncDec::ET_INCOMPL_MSG:\n" | |
193 | " case TTCN_EncDec::ET_LEN_ERR:\n" | |
194 | " ec.error((TTCN_EncDec::error_type_t)-rawr, " | |
195 | "\"Can not decode type '%%s', because incomplete message was received\", " | |
196 | "p_td.name);\n" | |
197 | " break;\n" | |
198 | " case 1:\n" /* from the generic -1 return value */ | |
199 | " default:\n" | |
200 | " ec.error(TTCN_EncDec::ET_INVAL_MSG, " | |
201 | "\"Can not decode type '%%s', because invalid " | |
202 | "message was received\", p_td.name);\n" | |
203 | " break;\n" | |
204 | " }\n" | |
205 | " break;}\n" | |
206 | " case TTCN_EncDec::CT_TEXT: {\n" | |
207 | " Limit_Token_List limit;\n" | |
208 | " TTCN_EncDec_ErrorContext ec(\"While TEXT-decoding type '%%s': \"," | |
209 | " p_td.name);\n" | |
210 | " if(!p_td.text)\n" | |
211 | " TTCN_EncDec_ErrorContext::error_internal\n" | |
212 | " (\"No TEXT descriptor available for type '%%s'.\", p_td.name);\n" | |
213 | " const unsigned char *b_data=p_buf.get_data();\n" | |
214 | " if(b_data[p_buf.get_len()-1]!='\\0'){\n" | |
215 | " p_buf.set_pos(p_buf.get_len());\n" | |
216 | " p_buf.put_zero(8,ORDER_LSB);\n" | |
217 | " p_buf.rewind();\n" | |
218 | " }\n" | |
219 | " if(TEXT_decode(p_td,p_buf,limit)<0)\n" | |
220 | " ec.error(TTCN_EncDec::ET_INCOMPL_MSG," | |
221 | "\"Can not decode type '%%s', because invalid or incomplete" | |
222 | " message was received\", p_td.name);\n" | |
223 | " break;}\n" | |
224 | /* XERSTUFF decoder */ | |
225 | " case TTCN_EncDec::CT_XER: {\n" | |
226 | " TTCN_EncDec_ErrorContext ec(" | |
227 | "\"While XER-decoding type '%%s': \", p_td.name);\n" | |
228 | " unsigned XER_coding=va_arg(pvar, unsigned);\n" | |
229 | " XER_encode_chk_coding(XER_coding, p_td);\n" | |
230 | " XmlReaderWrap reader(p_buf);\n" | |
231 | " for (int rd_ok=reader.Read(); rd_ok==1; rd_ok=reader.Read()) {\n" | |
232 | " if (reader.NodeType() == XML_READER_TYPE_ELEMENT) break;\n" | |
233 | " }\n" | |
feade998 | 234 | " XER_decode(*(p_td.xer), reader, XER_coding | XER_TOPLEVEL, XER_NONE, 0);\n" |
970ed795 EL |
235 | " size_t bytes = reader.ByteConsumed();\n" |
236 | " p_buf.set_pos(bytes);\n" | |
237 | " break;}\n" | |
238 | " case TTCN_EncDec::CT_JSON: {\n" | |
239 | " TTCN_EncDec_ErrorContext ec(\"While JSON-decoding type '%%s': \"," | |
240 | " p_td.name);\n" | |
241 | " if(!p_td.json)\n" | |
242 | " TTCN_EncDec_ErrorContext::error_internal\n" | |
243 | " (\"No JSON descriptor available for type '%%s'.\", p_td.name);\n" | |
244 | " JSON_Tokenizer tok((const char*)p_buf.get_data(), p_buf.get_len());\n" | |
245 | " if(JSON_decode(p_td, tok, false)<0)\n" | |
246 | " ec.error(TTCN_EncDec::ET_INCOMPL_MSG," | |
247 | "\"Can not decode type '%%s', because invalid or incomplete" | |
248 | " message was received\", p_td.name);\n" | |
249 | " p_buf.set_pos(tok.get_buf_pos());\n" | |
250 | " break;}\n" | |
251 | " default:\n" | |
252 | " TTCN_error(\"Unknown coding method requested to decode" | |
253 | " type '%%s'\", p_td.name);\n" | |
254 | " }\n" | |
255 | " va_end(pvar);\n" | |
256 | "}\n\n" | |
257 | #ifndef NDEBUG | |
258 | , __FUNCTION__, __LINE__ | |
259 | #endif | |
260 | , p_classname); | |
261 | ||
262 | *p_classdef=mputstr(*p_classdef, def); | |
263 | Free(def); | |
264 | *p_classsrc=mputstr(*p_classsrc, src); | |
265 | Free(src); | |
266 | } | |
267 | ||
268 | char *genRawFieldChecker(char *src, const rawAST_coding_taglist *taglist, | |
269 | boolean is_equal) | |
270 | { | |
271 | int i; | |
272 | for (i = 0; i < taglist->nElements; i++) { | |
273 | rawAST_coding_field_list *fields = taglist->fields + i; | |
274 | char *field_name = NULL; | |
275 | boolean first_expr = TRUE; | |
276 | int j; | |
277 | if (i > 0) src = mputstr(src, is_equal ? " || " : " && "); | |
278 | for (j = 0; j < fields->nElements; j++) { | |
279 | rawAST_coding_fields *field = fields->fields + j; | |
280 | if (j == 0) { | |
281 | /* this is the first field reference */ | |
282 | if (field->fieldtype == UNION_FIELD) | |
283 | field_name = mputprintf(field_name,"(*field_%s)",field->nthfieldname); | |
284 | else | |
285 | field_name = mputprintf(field_name,"field_%s", field->nthfieldname); | |
286 | } | |
287 | else { | |
288 | /* this is not the first field reference */ | |
289 | if (field->fieldtype == UNION_FIELD) { | |
290 | /* checking for the right selection within the union */ | |
291 | if (first_expr) { | |
292 | if (taglist->nElements > 1) src = mputc(src, '('); | |
293 | first_expr = FALSE; | |
294 | } | |
295 | else src = mputstr(src, is_equal ? " && " : " || "); | |
296 | src = mputprintf(src, "%s.get_selection() %s %s%s%s", field_name, | |
297 | is_equal ? "==" : "!=", fields->fields[j - 1].type, | |
298 | "::ALT_", field->nthfieldname); | |
299 | } | |
300 | /* appending the current field name to the field reference */ | |
301 | field_name = mputprintf(field_name, ".%s()", field->nthfieldname); | |
302 | } | |
303 | if (j < fields->nElements - 1 && field->fieldtype == OPTIONAL_FIELD) { | |
304 | /* this is not the last field in the chain and it is optional */ | |
305 | if (first_expr) { | |
306 | if (taglist->nElements > 1) src = mputc(src, '('); | |
307 | first_expr = FALSE; | |
308 | } | |
309 | else src = mputstr(src, is_equal ? " && " : " || "); | |
310 | /* check for the presence */ | |
311 | if (!is_equal) src = mputc(src, '!'); | |
312 | src = mputprintf(src, "%s.ispresent()", field_name); | |
313 | /* add an extra () to the field reference */ | |
314 | field_name = mputstr(field_name, "()"); | |
315 | } | |
316 | } | |
317 | if (!first_expr) src = mputstr(src, is_equal ? " && " : " || "); | |
318 | /* compare the referred field with the given value */ | |
319 | src = mputprintf(src, "%s %s %s", field_name, is_equal ? "==" : "!=", | |
320 | fields->value); | |
321 | if (!first_expr && taglist->nElements > 1) src = mputc(src, ')'); | |
322 | Free(field_name); | |
323 | } | |
324 | return src; | |
325 | } | |
326 | ||
327 | char *genRawTagChecker(char *src, const rawAST_coding_taglist *taglist) | |
328 | { | |
329 | int temp_tag, l; | |
330 | rawAST_coding_field_list temp_field; | |
331 | src = mputstr(src, " RAW_enc_tree* temp_leaf;\n"); | |
332 | for (temp_tag = 0; temp_tag < taglist->nElements; temp_tag++) { | |
333 | temp_field = taglist->fields[temp_tag]; | |
334 | src = mputprintf(src, " {\n" | |
3f84031e | 335 | " RAW_enc_tr_pos pr_pos%d;\n" |
336 | " pr_pos%d.level=myleaf.curr_pos.level+%d;\n" | |
337 | " int new_pos%d[]={", temp_tag, temp_tag, temp_field.nElements, temp_tag); | |
970ed795 EL |
338 | for (l = 0; l < temp_field.nElements; l++) { |
339 | src= mputprintf(src, "%s%d", l ? "," : "", temp_field.fields[l].nthfield); | |
340 | } | |
341 | src = mputprintf(src, "};\n" | |
3f84031e | 342 | " pr_pos%d.pos=init_new_tree_pos(myleaf.curr_pos,%d,new_pos%d);\n" |
343 | " temp_leaf = myleaf.get_node(pr_pos%d);\n" | |
344 | " if(temp_leaf != NULL){\n", temp_tag, temp_field.nElements, temp_tag, temp_tag); | |
970ed795 EL |
345 | if (temp_field.value[0] != ' ') { |
346 | src = mputprintf(src, " %s new_val = %s;\n" | |
347 | " new_val.RAW_encode(%s_descr_,*temp_leaf);\n", | |
348 | temp_field.fields[temp_field.nElements - 1].type, temp_field.value, | |
349 | temp_field.fields[temp_field.nElements - 1].typedescr); | |
350 | } | |
351 | else { | |
352 | src = mputprintf(src, " %s.RAW_encode(%s_descr_,*temp_leaf);\n", | |
353 | temp_field.value, temp_field.fields[temp_field.nElements - 1].typedescr); | |
354 | } | |
355 | src = mputstr(src, " } else"); | |
356 | } | |
357 | src = mputstr(src, " {\n" | |
358 | " TTCN_EncDec_ErrorContext::error\n" | |
359 | " (TTCN_EncDec::ET_OMITTED_TAG, \"Encoding a tagged, but omitted" | |
360 | " value.\");\n" | |
361 | " }\n"); | |
3f84031e | 362 | for (temp_tag = taglist->nElements - 1; temp_tag >= 0 ; temp_tag--) { |
363 | src = mputprintf(src, " free_tree_pos(pr_pos%d.pos);\n" | |
364 | " }\n", temp_tag); | |
970ed795 EL |
365 | } |
366 | return src; | |
367 | } |