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