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 "Basetype.hh" | |
9 | #include "../common/memory.h" | |
10 | #include "Logger.hh" | |
11 | #include "Error.hh" | |
12 | #include "BER.hh" | |
13 | #include "RAW.hh" | |
14 | #include "TEXT.hh" | |
15 | #include "XER.hh" | |
16 | #include "JSON.hh" | |
17 | #include "XmlReader.hh" | |
18 | #include "Module_list.hh" | |
af710487 | 19 | #include "Universal_charstring.hh" |
970ed795 EL |
20 | |
21 | #include <openssl/bn.h> | |
22 | ||
23 | #include <stdarg.h> | |
24 | #include <string.h> | |
25 | #include <limits.h> | |
26 | // Note: RT2-only classes (Record_Type, Record_Of_Type) and Base_Type methods | |
27 | // are in core2/Basetype2.cc | |
28 | ||
29 | boolean Base_Type::ispresent() const | |
30 | { | |
31 | TTCN_error("Base_Type::ispresent(): calling ispresent() on a non-optional field."); | |
32 | return TRUE; | |
33 | } | |
34 | ||
35 | void Base_Type::log() const | |
36 | { | |
37 | TTCN_Logger::log_event_str("<logging of this type is not implemented>"); | |
38 | } | |
39 | ||
40 | void Base_Type::encode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf, | |
41 | TTCN_EncDec::coding_t p_coding, ...) const | |
42 | { | |
43 | va_list pvar; | |
44 | va_start(pvar, p_coding); | |
45 | switch(p_coding) { | |
46 | case TTCN_EncDec::CT_BER: { | |
47 | TTCN_EncDec_ErrorContext ec("While BER-encoding type '%s': ", p_td.name); | |
48 | unsigned BER_coding=va_arg(pvar, unsigned); | |
49 | BER_encode_chk_coding(BER_coding); | |
50 | ASN_BER_TLV_t *tlv=BER_encode_TLV(p_td, BER_coding); | |
51 | tlv->put_in_buffer(p_buf); | |
52 | ASN_BER_TLV_t::destruct(tlv); | |
53 | break;} | |
54 | case TTCN_EncDec::CT_RAW: { | |
55 | TTCN_EncDec_ErrorContext ec("While RAW-encoding type '%s': ", p_td.name); | |
56 | if(!p_td.raw) | |
57 | TTCN_EncDec_ErrorContext::error_internal | |
58 | ("No RAW descriptor available for type '%s'.", p_td.name); | |
59 | RAW_enc_tr_pos rp; | |
60 | rp.level=0; | |
61 | rp.pos=NULL; | |
62 | RAW_enc_tree root(TRUE, NULL, &rp, 1, p_td.raw); | |
63 | RAW_encode(p_td, root); | |
64 | root.put_to_buf(p_buf); | |
65 | break;} | |
66 | case TTCN_EncDec::CT_TEXT: { | |
67 | TTCN_EncDec_ErrorContext ec("While TEXT-encoding type '%s': ", p_td.name); | |
68 | if(!p_td.text) | |
69 | TTCN_EncDec_ErrorContext::error_internal | |
70 | ("No TEXT descriptor available for type '%s'.", p_td.name); | |
71 | TEXT_encode(p_td,p_buf); | |
72 | break;} | |
73 | case TTCN_EncDec::CT_XER: { | |
74 | TTCN_EncDec_ErrorContext ec("While XER-encoding type '%s': ", p_td.name); | |
75 | if(!p_td.xer) TTCN_EncDec_ErrorContext::error_internal( | |
76 | "No XER descriptor available for type '%s'.", p_td.name); | |
77 | unsigned XER_coding=va_arg(pvar, unsigned); | |
af710487 | 78 | XER_encode(*(p_td.xer),p_buf, XER_coding, 0, 0); |
970ed795 EL |
79 | p_buf.put_c('\n'); |
80 | break;} | |
81 | case TTCN_EncDec::CT_JSON: { | |
82 | TTCN_EncDec_ErrorContext ec("While JSON-encoding type '%s': ", p_td.name); | |
83 | if(!p_td.json) | |
84 | TTCN_EncDec_ErrorContext::error_internal | |
85 | ("No JSON descriptor available for type '%s'.", p_td.name); | |
86 | JSON_Tokenizer tok(va_arg(pvar, int) != 0); | |
87 | JSON_encode(p_td, tok); | |
88 | p_buf.put_s(tok.get_buffer_length(), (const unsigned char*)tok.get_buffer()); | |
89 | break;} | |
90 | default: | |
91 | TTCN_error("Unknown coding method requested to encode type '%s'", | |
92 | p_td.name); | |
93 | } | |
94 | va_end(pvar); | |
95 | } | |
96 | ||
97 | void Base_Type::decode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf, | |
98 | TTCN_EncDec::coding_t p_coding, ...) | |
99 | { | |
100 | va_list pvar; | |
101 | va_start(pvar, p_coding); | |
102 | switch(p_coding) { | |
103 | case TTCN_EncDec::CT_BER: { | |
104 | TTCN_EncDec_ErrorContext ec("While BER-decoding type '%s': ", p_td.name); | |
105 | unsigned L_form=va_arg(pvar, unsigned); | |
106 | ASN_BER_TLV_t tlv; | |
107 | BER_decode_str2TLV(p_buf, tlv, L_form); | |
108 | BER_decode_TLV(p_td, tlv, L_form); | |
109 | if(tlv.isComplete) p_buf.increase_pos(tlv.get_len()); | |
110 | break;} | |
111 | case TTCN_EncDec::CT_RAW: { | |
112 | TTCN_EncDec_ErrorContext ec("While RAW-decoding type '%s': ", p_td.name); | |
113 | if(!p_td.raw) | |
114 | TTCN_EncDec_ErrorContext::error_internal | |
115 | ("No RAW descriptor available for type '%s'.", p_td.name); | |
116 | raw_order_t order; | |
117 | switch(p_td.raw->top_bit_order) { | |
118 | case TOP_BIT_LEFT: | |
119 | order=ORDER_LSB; | |
120 | break; | |
121 | case TOP_BIT_RIGHT: | |
122 | default: | |
123 | order=ORDER_MSB; | |
124 | } | |
125 | RAW_decode(p_td, p_buf, p_buf.get_len()*8, order); | |
126 | break;} | |
127 | case TTCN_EncDec::CT_TEXT: { | |
128 | Limit_Token_List limit; | |
129 | TTCN_EncDec_ErrorContext ec("While TEXT-decoding type '%s': ", p_td.name); | |
130 | if(!p_td.text) | |
131 | TTCN_EncDec_ErrorContext::error_internal | |
132 | ("No TEXT descriptor available for type '%s'.", p_td.name); | |
133 | const unsigned char *b=p_buf.get_data(); | |
134 | if(b[p_buf.get_len()-1]!='\0'){ | |
135 | p_buf.set_pos(p_buf.get_len()); | |
136 | p_buf.put_zero(8,ORDER_LSB); | |
137 | p_buf.rewind(); | |
138 | } | |
139 | if(TEXT_decode(p_td,p_buf,limit)<0) | |
140 | ec.error(TTCN_EncDec::ET_INCOMPL_MSG, | |
141 | "Can not decode type '%s', because invalid or incomplete" | |
142 | " message was received" | |
143 | , p_td.name); | |
144 | break;} | |
145 | case TTCN_EncDec::CT_XER: { | |
146 | TTCN_EncDec_ErrorContext ec("While XER-decoding type '%s': ", p_td.name); | |
147 | unsigned XER_coding=va_arg(pvar, unsigned); | |
148 | XmlReaderWrap reader(p_buf); | |
149 | for (int success=reader.Read(); success==1; success=reader.Read()) { | |
150 | if (reader.NodeType() == XML_READER_TYPE_ELEMENT) break; | |
151 | } | |
af710487 | 152 | XER_decode(*(p_td.xer), reader, XER_coding, 0); |
970ed795 EL |
153 | size_t bytes = reader.ByteConsumed(); |
154 | p_buf.set_pos(bytes); | |
155 | break;} | |
156 | case TTCN_EncDec::CT_JSON: { | |
157 | TTCN_EncDec_ErrorContext ec("While JSON-decoding type '%s': ", p_td.name); | |
158 | if(!p_td.json) | |
159 | TTCN_EncDec_ErrorContext::error_internal | |
160 | ("No JSON descriptor available for type '%s'.", p_td.name); | |
161 | JSON_Tokenizer tok((const char*)p_buf.get_data(), p_buf.get_len()); | |
162 | if(JSON_decode(p_td, tok, false)<0) | |
163 | ec.error(TTCN_EncDec::ET_INCOMPL_MSG, | |
164 | "Can not decode type '%s', because invalid or incomplete" | |
165 | " message was received" | |
166 | , p_td.name); | |
167 | p_buf.set_pos(tok.get_buf_pos()); | |
168 | break;} | |
169 | default: | |
170 | TTCN_error("Unknown coding method requested to decode type '%s'", | |
171 | p_td.name); | |
172 | } | |
173 | va_end(pvar); | |
174 | } | |
175 | ||
176 | void Base_Type::BER_chk_descr(const TTCN_Typedescriptor_t& p_td) | |
177 | { | |
178 | if(!p_td.ber) | |
179 | TTCN_EncDec_ErrorContext::error_internal | |
180 | ("No BER descriptor available for type '%s'.", p_td.name); | |
181 | } | |
182 | ||
183 | void Base_Type::BER_encode_chk_coding(unsigned& p_coding) | |
184 | { | |
185 | switch(p_coding) { | |
186 | case BER_ENCODE_CER: | |
187 | case BER_ENCODE_DER: | |
188 | break; | |
189 | default: | |
190 | TTCN_warning("Unknown BER encoding requested; using DER."); | |
191 | p_coding=BER_ENCODE_DER; | |
192 | break; | |
193 | } | |
194 | } | |
195 | ||
196 | void Base_Type::XER_encode_chk_coding(unsigned& p_coding, | |
197 | const TTCN_Typedescriptor_t& p_td) | |
198 | { | |
199 | if (!p_td.xer) { | |
200 | TTCN_EncDec_ErrorContext::error_internal | |
201 | ("No XER descriptor available for type '%s'.", p_td.name); | |
202 | } | |
203 | switch (p_coding) { | |
204 | case XER_BASIC: | |
205 | case XER_CANONICAL: | |
206 | case XER_EXTENDED: | |
207 | case XER_EXTENDED | XER_CANONICAL: | |
208 | break; | |
209 | default: | |
210 | TTCN_warning("Unknown XER encoding requested; using Basic XER."); | |
211 | p_coding = XER_BASIC; | |
212 | break; | |
213 | } | |
214 | } | |
215 | ||
216 | static const cbyte empty_tag_end[4] = "/>\n"; | |
217 | ||
218 | int Base_Type::begin_xml(const XERdescriptor_t& p_td, TTCN_Buffer& p_buf, | |
219 | unsigned int& flavor, int indent, bool empty, | |
220 | collector_fn collector, const char *type_atr) const | |
221 | { | |
222 | const int indenting = !is_canonical(flavor); | |
223 | const int exer = is_exer(flavor); | |
224 | int omit_tag = (indent != 0) // can never omit the tag at the toplevel | |
225 | && ( ((flavor & XER_RECOF) // can remove the tag even if not EXER | |
226 | && !(exer && (flavor & BXER_EMPTY_ELEM))) // except 26.6, 26.7 | |
227 | || (exer /*&& */ | |
228 | && ( (p_td.xer_bits & (UNTAGGED|ANY_ATTRIBUTES|ANY_ELEMENT)) | |
229 | || (flavor & (EMBED_VALUES|XER_LIST|ANY_ATTRIBUTES|USE_NIL|USE_TYPE_ATTR))))); | |
230 | ||
231 | // If a default namespace is in effect (uri but no prefix) and the type | |
232 | // is unqualified, the default namespace must be canceled; otherwise | |
233 | // an XML tag without a ns prefix looks like it belongs to the def.namespace | |
234 | const boolean empty_ns_hack = exer && !omit_tag && (indent > 0) | |
235 | && (p_td.xer_bits & FORM_UNQUALIFIED) | |
236 | && (flavor & DEF_NS_PRESENT); | |
237 | ||
238 | if (exer && (p_td.xer_bits & XER_ATTRIBUTE)) { | |
239 | begin_attribute(p_td, p_buf); | |
240 | } | |
241 | else if (!omit_tag) { // full tag | |
242 | if (indenting) do_indent(p_buf, indent); | |
243 | p_buf.put_c('<'); | |
244 | if (exer) write_ns_prefix(p_td, p_buf); | |
245 | ||
246 | const namespace_t *ns_info = NULL; | |
247 | bool namespaces_needed = false; | |
248 | if (exer) { | |
249 | if (p_td.my_module != NULL && p_td.ns_index != -1) { | |
250 | ns_info = p_td.my_module->get_ns(p_td.ns_index); | |
251 | } | |
252 | ||
253 | namespaces_needed = exer && //!(p_td.xer_bits & FORM_UNQUALIFIED) && | |
254 | (indent==0 // top-level type | |
255 | || (ns_info && *ns_info->px == '\0' // own ns is prefixless | |
256 | && (flavor & DEF_NS_SQUASHED)) | |
257 | ); | |
258 | } | |
259 | ||
260 | size_t num_collected = 0; | |
261 | char **collected_ns = NULL; | |
262 | bool def_ns = false; | |
263 | if (namespaces_needed) { | |
264 | collected_ns = (this->*collector)(p_td, num_collected, def_ns); | |
265 | } | |
266 | ||
267 | p_buf.put_s((size_t)p_td.namelens[exer] - 2, (cbyte*)p_td.names[exer]); | |
268 | ||
269 | if (namespaces_needed) { | |
270 | for (size_t cur_coll = 0; cur_coll < num_collected; ++cur_coll) { | |
271 | p_buf.put_s(strlen(collected_ns[cur_coll]), (cbyte*)collected_ns[cur_coll]); | |
272 | Free(collected_ns[cur_coll]); // job done | |
273 | } | |
274 | Free(collected_ns); | |
275 | } | |
276 | ||
277 | if (empty_ns_hack) { | |
278 | p_buf.put_s(9, (cbyte*)" xmlns=''"); | |
279 | flavor &= ~DEF_NS_PRESENT; | |
280 | flavor |= DEF_NS_SQUASHED; | |
281 | } | |
282 | else if (def_ns) { | |
283 | flavor &= ~DEF_NS_SQUASHED; | |
284 | flavor |= DEF_NS_PRESENT; | |
285 | } | |
286 | ||
287 | if (type_atr) { | |
288 | p_buf.put_s(mstrlen(const_cast<char*>(type_atr)), (cbyte*)type_atr); | |
289 | } | |
290 | // now close the tag | |
291 | if (empty) { | |
292 | p_buf.put_s(2 + indenting, empty_tag_end); | |
293 | } | |
294 | else { | |
295 | p_buf.put_s( | |
296 | 1 + (indenting | |
297 | && !(flavor & SIMPLE_TYPE) | |
298 | && !(exer && (p_td.xer_bits & (XER_LIST|USE_TYPE_ATTR)))), | |
299 | empty_tag_end+1); | |
300 | } | |
301 | } | |
302 | else { // tag is omitted | |
303 | // If the outer XML element optimistically wrote a newline after its start tag, | |
304 | // back up over it. | |
305 | size_t buf_used = p_buf.get_len(); | |
306 | if (exer && (flavor & USE_NIL) && (buf_used-- > 0) && // sequence point! | |
307 | (p_buf.get_data()[buf_used] == '\n')) { | |
308 | p_buf.increase_length((size_t)-1); // back up over the newline | |
309 | omit_tag = -1; // to help fix HO85831 | |
310 | } | |
311 | } | |
312 | ||
313 | Free(const_cast<char*>(type_atr)); | |
314 | ||
315 | return omit_tag; | |
316 | } | |
317 | ||
318 | void Base_Type::end_xml (const XERdescriptor_t& p_td, TTCN_Buffer& p_buf, | |
319 | unsigned int flavor, int indent, bool empty) const | |
320 | { | |
321 | int exer = is_exer(flavor); | |
322 | int indenting = !is_canonical(flavor); | |
323 | bool omit_tag = (indent != 0) // can never omit the tag at the toplevel | |
324 | && ( ((flavor & XER_RECOF) // can remove the tag even if not EXER | |
325 | && !(exer && (flavor & BXER_EMPTY_ELEM))) // except 26.6, 26.7 | |
326 | || (exer /*&& */ | |
327 | && ( (p_td.xer_bits & (UNTAGGED|ANY_ATTRIBUTES|ANY_ELEMENT)) | |
328 | || (flavor & (EMBED_VALUES|XER_LIST|ANY_ATTRIBUTES|USE_NIL|USE_TYPE_ATTR))))); | |
329 | ||
330 | if (exer && (p_td.xer_bits & XER_ATTRIBUTE)) { | |
331 | p_buf.put_c('\''); | |
332 | } | |
333 | else if (!empty && !omit_tag) { | |
334 | // now close the tag | |
335 | if (indenting && !(flavor & SIMPLE_TYPE)) do_indent(p_buf, indent); | |
336 | p_buf.put_s(2, (cbyte*)"</"); | |
337 | if (exer) write_ns_prefix(p_td, p_buf); | |
338 | p_buf.put_s((size_t)p_td.namelens[exer]-1+indenting, (cbyte*)p_td.names[exer]); | |
339 | } | |
340 | ||
341 | } | |
342 | ||
343 | ||
344 | ASN_BER_TLV_t* Base_Type::BER_encode_chk_bound(boolean p_isbound) | |
345 | { | |
346 | if(!p_isbound) { | |
347 | TTCN_EncDec_ErrorContext::error | |
348 | (TTCN_EncDec::ET_UNBOUND, "Encoding an unbound value."); | |
349 | ASN_BER_TLV_t *new_tlv=ASN_BER_TLV_t::construct(0, NULL); | |
350 | new_tlv->Tlen=0; | |
351 | new_tlv->Tstr=NULL; | |
352 | new_tlv->Llen=0; | |
353 | new_tlv->Lstr=NULL; | |
354 | return new_tlv; | |
355 | } | |
356 | else return NULL; | |
357 | } | |
358 | ||
359 | // Called only from the two places in BER_encode_TLV_OCTETSTRING, below. | |
360 | void Base_Type::BER_encode_putoctets_OCTETSTRING | |
361 | (unsigned char *target, | |
362 | unsigned int octetnum_start, unsigned int octet_count, | |
363 | int p_nof_octets, const unsigned char *p_octets_ptr) | |
364 | { | |
365 | if( octetnum_start > static_cast<unsigned int>(p_nof_octets) | |
366 | || octetnum_start+octet_count > static_cast<unsigned int>(p_nof_octets)) | |
367 | TTCN_EncDec_ErrorContext::error_internal | |
368 | ("In Base_Type::BER_encode_putoctets_OCTETSTRING(): Index overflow."); | |
369 | memcpy(target, &p_octets_ptr[octetnum_start], octet_count); | |
370 | } | |
371 | ||
372 | ASN_BER_TLV_t* Base_Type::BER_encode_TLV_OCTETSTRING | |
373 | (unsigned p_coding, | |
374 | int p_nof_octets, const unsigned char *p_octets_ptr) | |
375 | { | |
376 | unsigned char *V_ptr; | |
377 | size_t V_len; | |
378 | unsigned int nof_fragments=0; | |
379 | ||
380 | if(p_coding==BER_ENCODE_CER) { | |
381 | nof_fragments=(p_nof_octets+999)/1000; | |
382 | if(!nof_fragments) nof_fragments=1; | |
383 | } | |
384 | else /*if(coding==BER_ENCODE_DER)*/ { | |
385 | nof_fragments=1; | |
386 | } | |
387 | ||
388 | ASN_BER_TLV_t *new_tlv=NULL; | |
389 | boolean is_constructed=nof_fragments>1; | |
390 | if(!is_constructed) { | |
391 | V_len=p_nof_octets; | |
392 | V_ptr=(unsigned char*)Malloc(V_len); | |
393 | BER_encode_putoctets_OCTETSTRING(V_ptr, 0, p_nof_octets, | |
394 | p_nof_octets, p_octets_ptr); | |
395 | new_tlv=ASN_BER_TLV_t::construct(V_len, V_ptr); | |
396 | } | |
397 | else { // is constructed | |
398 | ASN_BER_TLV_t *tmp_tlv=NULL; | |
399 | new_tlv=ASN_BER_TLV_t::construct(NULL); | |
400 | unsigned int rest_octets=p_nof_octets-(nof_fragments-1)*1000; | |
401 | V_len=1000; | |
402 | for(unsigned int i=0; i<nof_fragments; i++) { | |
403 | if(i==nof_fragments-1) V_len=rest_octets; | |
404 | V_ptr=(unsigned char*)Malloc(V_len); | |
405 | BER_encode_putoctets_OCTETSTRING(V_ptr, i*1000, V_len, | |
406 | p_nof_octets, p_octets_ptr); | |
407 | tmp_tlv=ASN_BER_TLV_t::construct(V_len, V_ptr); | |
408 | tmp_tlv=ASN_BER_V2TLV(tmp_tlv, OCTETSTRING_descr_, p_coding); | |
409 | new_tlv->add_TLV(tmp_tlv); | |
410 | } | |
411 | } | |
412 | return new_tlv; | |
413 | } | |
414 | ||
415 | /* | |
416 | // for debugging purposes | |
417 | static std::string bignum_as_bin(const BIGNUM* const BN) { | |
418 | int bytes = BN_num_bytes(BN); | |
419 | unsigned char* bn_as_bin = (unsigned char*) Malloc(bytes); | |
420 | BN_bn2bin(BN, bn_as_bin); | |
421 | ||
422 | std::string result; | |
423 | for (int i = 0; i < bytes; ++i) { | |
424 | result.append(char_as_bin(bn_as_bin[i])); | |
425 | result.append(" "); | |
426 | } | |
427 | Free(bn_as_bin); | |
428 | return result; | |
429 | } | |
430 | ||
431 | static std::string int_as_bin(int myInt) { | |
432 | std::string result; | |
433 | for (int i = sizeof(myInt) - 1; i >= 0; --i) { | |
434 | char current = (myInt >> (i * 8)) & 0xFF; | |
435 | result.append(char_as_bin(current)); | |
436 | } | |
437 | return result; | |
438 | } | |
439 | ||
440 | static std::string char_as_bin(unsigned char ch) { | |
441 | std::string result; | |
442 | for (int i = 0; i < 8; ++i) { | |
443 | result.append((ch & 0x80) == 0x80 ? "1" : "0"); | |
444 | ch <<= 1; | |
445 | } | |
446 | return result; | |
447 | } | |
448 | ||
449 | static std::string chars_as_bin(const unsigned char* const chars, int len) { | |
450 | std::string result; | |
451 | for (int i = 0; i < len; ++i) { | |
452 | result.append(char_as_bin(chars[i])); | |
453 | if (i != len - 1) { | |
454 | result.append(" "); | |
455 | } | |
456 | } | |
457 | return result; | |
458 | } | |
459 | */ | |
460 | ||
461 | ASN_BER_TLV_t *Base_Type::BER_encode_TLV_INTEGER(unsigned, | |
462 | const int_val_t& p_int_val) | |
463 | { | |
464 | if(p_int_val.is_native()){ | |
465 | RInt p_int_val_int=p_int_val.get_val(); | |
466 | // Determine the number of octets to be used in the encoding. | |
467 | unsigned long ulong_val=p_int_val_int >= 0 | |
468 | ?static_cast<unsigned long>(p_int_val_int): | |
469 | ~static_cast<unsigned long>(p_int_val_int); | |
470 | size_t V_len=1; | |
471 | ulong_val>>=7; | |
472 | while(ulong_val!=0){ | |
473 | V_len++; | |
474 | ulong_val>>=8; | |
475 | } | |
476 | ASN_BER_TLV_t *new_tlv=ASN_BER_TLV_t::construct(V_len,NULL); | |
477 | // Already in 2's complement encoding. | |
478 | ulong_val=static_cast<unsigned long>(p_int_val_int); | |
479 | for(size_t i=V_len;i>0;i--){ | |
480 | new_tlv->V.str.Vstr[i-1]=ulong_val&0xFF; | |
481 | ulong_val>>=8; | |
482 | } | |
483 | return new_tlv; | |
484 | } | |
485 | ||
486 | // bignum | |
487 | ||
488 | const BIGNUM* const D = p_int_val.get_val_openssl(); | |
489 | if (BN_is_zero(D)) { | |
490 | ASN_BER_TLV_t *new_tlv=ASN_BER_TLV_t::construct(1,NULL); | |
491 | new_tlv->V.str.Vstr[0] = 0; | |
492 | return new_tlv; | |
493 | } | |
494 | ||
495 | size_t num_bytes = BN_num_bytes(D); | |
496 | unsigned char* bn_as_bin = (unsigned char*) Malloc(num_bytes); | |
497 | BN_bn2bin(D, bn_as_bin); | |
498 | ||
499 | bool pad = false; | |
500 | if (BN_is_negative(D)) { | |
501 | for(size_t i = 0; i < num_bytes; ++i){ | |
502 | bn_as_bin[i] = ~bn_as_bin[i]; | |
503 | } | |
504 | ||
505 | // add one | |
506 | bool stop = false; | |
507 | for (int i = num_bytes - 1; i >= 0 && !stop; --i) { | |
508 | for (int j = 0; j < 8 && !stop; ++j) { | |
509 | unsigned char mask = (0x1 << j); | |
510 | if (!(bn_as_bin[i] & mask)) { | |
511 | bn_as_bin[i] |= mask; | |
512 | stop = true; | |
513 | } else { | |
514 | bn_as_bin[i] ^= mask; | |
515 | } | |
516 | } | |
517 | } | |
518 | pad = !(bn_as_bin[0] & 0x80); | |
519 | } else { | |
520 | pad = bn_as_bin[0] & 0x80; | |
521 | } | |
522 | ||
523 | ASN_BER_TLV_t* new_tlv = ASN_BER_TLV_t::construct(num_bytes + pad, NULL); | |
524 | if (pad) { | |
525 | new_tlv->V.str.Vstr[0] = BN_is_negative(D) ? 0xFF : 0x0; | |
526 | } | |
527 | ||
528 | memcpy(new_tlv->V.str.Vstr + pad, bn_as_bin, num_bytes); | |
529 | ||
530 | Free(bn_as_bin); | |
531 | return new_tlv; | |
532 | } | |
533 | ||
534 | ASN_BER_TLV_t *Base_Type::BER_encode_TLV_INTEGER(unsigned p_coding, | |
535 | const int& p_int_val) | |
536 | { | |
537 | int_val_t p_int_val_val(p_int_val); | |
538 | return BER_encode_TLV_INTEGER(p_coding, p_int_val_val); | |
539 | } | |
540 | ||
541 | void Base_Type::BER_encode_chk_enum_valid(const TTCN_Typedescriptor_t& p_td, | |
542 | boolean p_isvalid, int p_value) | |
543 | { | |
544 | if(!p_isvalid) | |
545 | TTCN_EncDec_ErrorContext::error | |
546 | (TTCN_EncDec::ET_ENC_ENUM, | |
547 | "Encoding unknown value '%d' for enumerated type '%s'.", | |
548 | p_value, p_td.name); | |
549 | ||
550 | } | |
551 | ||
552 | void Base_Type::BER_decode_str2TLV(TTCN_Buffer& p_buf, ASN_BER_TLV_t& p_tlv, | |
553 | unsigned L_form) | |
554 | { | |
555 | if(!ASN_BER_str2TLV(p_buf.get_read_len(), p_buf.get_read_data(), | |
556 | p_tlv, L_form)) | |
557 | TTCN_EncDec_ErrorContext::error | |
558 | (TTCN_EncDec::ET_INCOMPL_MSG, "TLV is not complete."); | |
559 | } | |
560 | ||
561 | boolean Base_Type::BER_decode_constdTLV_next(const ASN_BER_TLV_t& p_tlv, | |
562 | size_t& V_pos, | |
563 | unsigned L_form, | |
564 | ASN_BER_TLV_t& p_target_tlv) | |
565 | { | |
566 | if(p_tlv.V.str.Vlen<=V_pos) { | |
567 | if(!p_tlv.isLenDefinite) | |
568 | TTCN_EncDec_ErrorContext::error | |
569 | (TTCN_EncDec::ET_INCOMPL_MSG, | |
570 | "Missing end-of-contents octet in the indefinite length" | |
571 | " constructed TLV."); | |
572 | return FALSE; | |
573 | } | |
574 | if(!ASN_BER_str2TLV(p_tlv.V.str.Vlen-V_pos, | |
575 | p_tlv.V.str.Vstr+V_pos, p_target_tlv, L_form)) { | |
576 | TTCN_EncDec_ErrorContext::error | |
577 | (TTCN_EncDec::ET_INCOMPL_MSG, | |
578 | "Incomplete TLV in the constructed TLV."); | |
579 | } | |
580 | if(!p_tlv.isLenDefinite && p_target_tlv.tagnumber==0 | |
581 | && p_target_tlv.tagclass==ASN_TAG_UNIV) | |
582 | return FALSE; | |
583 | V_pos+=p_target_tlv.get_len(); | |
584 | return TRUE; | |
585 | } | |
586 | ||
587 | void Base_Type::BER_decode_constdTLV_end(const ASN_BER_TLV_t& p_tlv, | |
588 | size_t& V_pos, | |
589 | unsigned L_form, | |
590 | ASN_BER_TLV_t& p_target_tlv, | |
591 | boolean tlv_present) | |
592 | { | |
593 | if(tlv_present | |
594 | || BER_decode_constdTLV_next(p_tlv, V_pos, L_form, p_target_tlv)) { | |
595 | TTCN_EncDec_ErrorContext::error | |
596 | (TTCN_EncDec::ET_SUPERFL, | |
597 | "Superfluous TLV(s) at the end of constructed TLV."); | |
598 | } | |
599 | } | |
600 | ||
601 | static void BER_decode_chk_tag(const ASN_Tag_t& tag, | |
602 | const ASN_BER_TLV_t& tlv) | |
603 | { | |
604 | if (tlv.isTagComplete && | |
605 | (tag.tagclass != tlv.tagclass || tag.tagnumber != tlv.tagnumber)) { | |
606 | ASN_Tag_t rcvdtag; | |
607 | rcvdtag.tagclass=tlv.tagclass; | |
608 | rcvdtag.tagnumber=tlv.tagnumber; | |
609 | char *rcvdstr=rcvdtag.print(); | |
610 | try { | |
611 | TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_TAG, | |
612 | "Tag mismatch: Received: %s.", rcvdstr); | |
613 | } catch (...) { | |
614 | Free(rcvdstr); | |
615 | throw; | |
616 | } | |
617 | Free(rcvdstr); | |
618 | } | |
619 | } | |
620 | ||
621 | void Base_Type::BER_decode_strip_tags(const ASN_BERdescriptor_t& p_ber, | |
622 | const ASN_BER_TLV_t& p_tlv, | |
623 | unsigned L_form, | |
624 | ASN_BER_TLV_t& stripped_tlv) | |
625 | { | |
626 | size_t i=p_ber.n_tags; | |
627 | if(i==0) { | |
628 | stripped_tlv=p_tlv; | |
629 | return; | |
630 | } | |
631 | char *expectedstr=p_ber.print_tags(); | |
632 | TTCN_EncDec_ErrorContext ec("While checking tags (expecting %s): ", | |
633 | expectedstr); | |
634 | Free(expectedstr); | |
635 | if(i==1) { | |
636 | BER_decode_chk_tag(p_ber.tags[0], p_tlv); | |
637 | stripped_tlv=p_tlv; | |
638 | return; | |
639 | } | |
640 | ASN_BER_TLV_t curr_tlv=p_tlv; | |
641 | boolean doit=TRUE; | |
642 | i--; | |
643 | while(doit) { | |
644 | TTCN_EncDec_ErrorContext ec2("At pos #%lu: ", | |
645 | (unsigned long) (p_ber.n_tags - i)); | |
646 | BER_decode_chk_tag(p_ber.tags[i], curr_tlv); | |
647 | if(i!=0) { // not the innermost tag | |
648 | if(!curr_tlv.isConstructed) { | |
649 | ec2.error(TTCN_EncDec::ET_TAG, | |
650 | "The other (innermost %lu) tag(s) are missing.", (unsigned long) i); | |
651 | doit=FALSE; | |
652 | stripped_tlv=curr_tlv; | |
653 | } | |
654 | else { // O.K., is constructed | |
655 | size_t V_pos=0; | |
656 | BER_decode_constdTLV_next(curr_tlv, V_pos, L_form, stripped_tlv); | |
657 | // if superfluous...? | |
658 | ASN_BER_TLV_t endchecker_tlv; | |
659 | BER_decode_constdTLV_end(curr_tlv, V_pos, L_form, endchecker_tlv, | |
660 | FALSE); | |
661 | curr_tlv=stripped_tlv; | |
662 | i--; | |
663 | } // is constructed | |
664 | } // not the innermost | |
665 | else { // innermost tag | |
666 | doit=FALSE; | |
667 | } | |
668 | } // while doit | |
669 | } | |
670 | ||
671 | void Base_Type::BER_decode_getoctets_OCTETSTRING | |
672 | (const unsigned char *source, size_t s_len, | |
673 | unsigned int& octetnum_start, | |
674 | int& p_nof_octets, unsigned char *p_octets_ptr) | |
675 | { | |
676 | p_nof_octets=octetnum_start+s_len; | |
677 | memcpy(&p_octets_ptr[octetnum_start], source, s_len); | |
678 | octetnum_start+=s_len; | |
679 | } | |
680 | ||
681 | void Base_Type::BER_decode_TLV_OCTETSTRING | |
682 | (const ASN_BER_TLV_t& p_tlv, unsigned L_form, | |
683 | unsigned int& octetnum_start, | |
684 | int& p_nof_octets, unsigned char *p_octets_ptr) | |
685 | { | |
686 | if(!p_tlv.isConstructed) { | |
687 | BER_decode_getoctets_OCTETSTRING | |
688 | (p_tlv.V.str.Vstr, p_tlv.V.str.Vlen, octetnum_start, | |
689 | p_nof_octets, p_octets_ptr); | |
690 | } | |
691 | else { // is constructed | |
692 | ASN_BER_TLV_t tlv2; | |
693 | size_t V_pos=0; | |
694 | boolean doit=TRUE; | |
695 | while(doit) { | |
696 | if(!ASN_BER_str2TLV(p_tlv.V.str.Vlen-V_pos, p_tlv.V.str.Vstr+V_pos, | |
697 | tlv2, L_form)) { | |
698 | TTCN_EncDec_ErrorContext::error | |
699 | (TTCN_EncDec::ET_INCOMPL_MSG, | |
700 | "Incomplete TLV in a constructed OCTETSTRING TLV."); | |
701 | return; | |
702 | } | |
703 | if(!p_tlv.isLenDefinite && tlv2.tagnumber==0 | |
704 | && tlv2.tagclass==ASN_TAG_UNIV) | |
705 | doit=FALSE; // End-of-contents | |
706 | if(doit) { | |
707 | ASN_BER_TLV_t stripped_tlv; | |
708 | BER_decode_strip_tags(OCTETSTRING_ber_, tlv2, L_form, stripped_tlv); | |
709 | BER_decode_TLV_OCTETSTRING(tlv2, L_form, octetnum_start, | |
710 | p_nof_octets, p_octets_ptr); | |
711 | V_pos+=tlv2.get_len(); | |
712 | if(V_pos>=p_tlv.V.str.Vlen) doit=FALSE; | |
713 | } | |
714 | } // while(doit) | |
715 | } // else / is constructed | |
716 | } | |
717 | ||
718 | ||
719 | ||
720 | boolean Base_Type::BER_decode_TLV_INTEGER(const ASN_BER_TLV_t& p_tlv, | |
721 | unsigned, int_val_t& p_int_val) | |
722 | { | |
723 | p_tlv.chk_constructed_flag(FALSE); | |
724 | if (!p_tlv.isComplete) return FALSE; | |
725 | if (!p_tlv.V_tlvs_selected && p_tlv.V.str.Vlen == 0) { | |
726 | TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_INVAL_MSG, | |
727 | "Length of V-part is 0."); | |
728 | return FALSE; | |
729 | } | |
730 | ||
731 | const size_t Vlen = p_tlv.V.str.Vlen; | |
732 | ||
733 | if (Vlen > sizeof(RInt)) { // Bignum | |
734 | ||
735 | const bool negative = p_tlv.V.str.Vstr[0] & 0x80; | |
736 | BIGNUM *D = BN_new(); | |
737 | ||
738 | if (negative) { | |
739 | unsigned char* const Vstr = (unsigned char*) Malloc(Vlen); | |
740 | memcpy(Vstr, p_tlv.V.str.Vstr, Vlen); | |
741 | // -1 | |
742 | bool stop = false; | |
743 | for (int i = Vlen - 1; i >= 0 && !stop; --i) { | |
744 | for(int j = 0; j < 8 && !stop; ++j) { | |
745 | unsigned char mask = (0x1 << j); | |
746 | if (Vstr[i] & mask) { | |
747 | Vstr[i] ^= mask; | |
748 | stop = true; | |
749 | } else { | |
750 | Vstr[i] |= mask; | |
751 | } | |
752 | } | |
753 | } | |
754 | ||
755 | for (size_t i = 0; i < Vlen; ++i) { | |
756 | Vstr[i] = ~Vstr[i]; | |
757 | } | |
758 | ||
759 | BN_bin2bn(Vstr, Vlen, D); | |
760 | Free(Vstr); | |
761 | } else { // positive case | |
762 | BN_bin2bn(p_tlv.V.str.Vstr, Vlen, D); | |
763 | } | |
764 | ||
765 | BN_set_negative(D, negative); | |
766 | p_int_val = int_val_t(D); | |
767 | return TRUE; | |
768 | } // bignum | |
769 | ||
770 | // Native int Vlen <= sizeof(RInt) | |
771 | const unsigned char* const Vstr = p_tlv.V.str.Vstr; | |
772 | RInt int_val = 0; | |
773 | if (Vstr[0] & 0x80) { // negative | |
774 | // the first bytes should be 1-s | |
775 | // e.g. -1 encoded on 32 bits: 11111111111111111111111111111111 | |
776 | // e.g. -1 encoded on 8 bits: 11111111 | |
777 | // [(sizeof(RInt)-Vlen)*8 ][Vlen*8] | |
778 | // [ sizeof(RInt)*8 ] | |
779 | ||
780 | for (size_t i = 0; i < sizeof(RInt) - Vlen; ++i) { | |
781 | int_val |= 0xFF; | |
782 | int_val <<= 8; | |
783 | } | |
784 | } | |
785 | ||
786 | int_val |= p_tlv.V.str.Vstr[0]; | |
787 | for (size_t i = 1; i < Vlen; ++i) { | |
788 | int_val <<= 8; | |
789 | int_val |= p_tlv.V.str.Vstr[i]; | |
790 | } | |
791 | ||
792 | p_int_val = int_val_t(int_val); | |
793 | return TRUE; | |
794 | } | |
795 | ||
796 | boolean Base_Type::BER_decode_TLV_INTEGER(const ASN_BER_TLV_t& p_tlv, | |
797 | unsigned L_form, int& p_int_val) | |
798 | { | |
799 | int_val_t p_int_val_val(p_int_val); | |
800 | boolean ret_val = BER_decode_TLV_INTEGER(p_tlv, L_form, p_int_val_val); | |
801 | if (p_int_val_val.is_native()) { | |
802 | p_int_val = p_int_val_val.get_val(); | |
803 | } else { | |
804 | TTCN_warning("Large integer value was decoded and it can't be returned " | |
805 | "as a native `int'"); | |
806 | } | |
807 | return ret_val; | |
808 | } | |
809 | ||
810 | /* | |
811 | ||
812 | // Actually, this is not used, but when we ever need a | |
813 | // type-independent integer decoding, then we can move this to | |
814 | // Basetype.hh. It is so beautiful and wonderful, I did not wanted | |
815 | // this to get lost. :) | |
816 | ||
817 | template<typename int_type> | |
818 | void Base_Type::BER_decode_TLV_INTEGER | |
819 | (const ASN_BER_TLV_t& p_tlv, unsigned L_form, int_type& p_intval) | |
820 | { | |
821 | boolean overflow_flag=FALSE; | |
822 | p_tlv.chk_constructed_flag(FALSE); | |
823 | if(!p_tlv.V_tlvs_selected && p_tlv.V.str.Vlen==0) { | |
824 | TTCN_EncDec_ErrorContext::error | |
825 | (TTCN_EncDec::ET_INVAL_MSG, "Length of V-part is 0."); | |
826 | p_intval=static_cast<int_type>(0); | |
827 | return; | |
828 | } | |
829 | int_type tmp_int=static_cast<int_type>(p_tlv.V.str.Vstr[0] & 0x7F); | |
830 | for(size_t i=1; i<p_tlv.V.str.Vlen; i++) { | |
831 | p_intval=tmp_int; | |
832 | tmp_int=static_cast<int_type>(256*tmp_int); | |
833 | if(tmp_int<p_intval) overflow_flag=TRUE; | |
834 | tmp_int=static_cast<int_type>(tmp_int+p_tlv.V.str.Vstr[i]); | |
835 | } | |
836 | if(p_tlv.V.str.Vstr[0] & 0x80) { // negative | |
837 | int_type highbit=static_cast<int_type>(1); | |
838 | for(size_t i=0; i<p_tlv.V.str.Vlen*8-1; i++) { | |
839 | int_type backup=highbit; | |
840 | highbit=static_cast<int_type>(2*highbit); | |
841 | if(highbit/2!=backup) overflow_flag=TRUE; | |
842 | } | |
843 | p_intval=static_cast<int_type>(tmp_int-highbit); | |
844 | } | |
845 | else { // positive | |
846 | p_intval=tmp_int; | |
847 | } | |
848 | if(overflow_flag) | |
849 | TTCN_EncDec_ErrorContext::error | |
850 | (TTCN_EncDec::ET_REPR, | |
851 | "Value is too big (%lu octets).", p_tlv.V.str.Vlen); | |
852 | } | |
853 | ||
854 | */ | |
855 | ||
856 | boolean Base_Type::BER_decode_TLV_CHOICE(const ASN_BERdescriptor_t& p_ber, | |
857 | const ASN_BER_TLV_t& p_tlv, | |
858 | unsigned L_form, | |
859 | ASN_BER_TLV_t& p_target_tlv) | |
860 | { | |
861 | if(p_ber.n_tags>0) { | |
862 | size_t V_pos=0; | |
863 | p_tlv.chk_constructed_flag(TRUE); | |
864 | if(!BER_decode_constdTLV_next(p_tlv, V_pos, L_form, p_target_tlv)) | |
865 | return FALSE; | |
866 | } | |
867 | else p_target_tlv=p_tlv; | |
868 | return TRUE; | |
869 | } | |
870 | ||
871 | boolean Base_Type::BER_decode_CHOICE_selection(boolean select_result, | |
872 | const ASN_BER_TLV_t& p_tlv) | |
873 | { | |
874 | if(select_result) return TRUE; | |
875 | ASN_Tag_t rcvd_tag; | |
876 | rcvd_tag.tagclass=p_tlv.tagclass; | |
877 | rcvd_tag.tagnumber=p_tlv.tagnumber; | |
878 | char *rcvd_str=rcvd_tag.print(); | |
879 | try { | |
880 | TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_TAG, | |
881 | "Invalid tag or unknown alternative: %s.", rcvd_str); | |
882 | } catch (...) { | |
883 | Free(rcvd_str); | |
884 | throw; | |
885 | } | |
886 | Free(rcvd_str); | |
887 | return FALSE; | |
888 | } | |
889 | ||
890 | void Base_Type::BER_decode_chk_enum_valid(const TTCN_Typedescriptor_t& p_td, | |
891 | boolean p_isvalid, int p_value) | |
892 | { | |
893 | /** \todo If extensible ENUMERATED is supported (for example, in the | |
894 | * typedescriptor there is something...), then give different error | |
895 | * message depending on that flag. */ | |
896 | if(!p_isvalid) | |
897 | TTCN_EncDec_ErrorContext::error | |
898 | (TTCN_EncDec::ET_DEC_ENUM, | |
899 | "Unknown value '%d' received for enumerated type '%s'.", | |
900 | p_value, p_td.name); | |
901 | } | |
902 | ||
903 | ASN_BER_TLV_t* | |
904 | Base_Type::BER_encode_TLV(const TTCN_Typedescriptor_t& p_td, | |
905 | unsigned) const | |
906 | { | |
907 | BER_chk_descr(p_td); | |
908 | ASN_BER_TLV_t *tlv=BER_encode_chk_bound(TRUE); | |
909 | if(tlv) return tlv; | |
910 | TTCN_EncDec_ErrorContext::error_internal | |
911 | ("BER_encode_V() not implemented for type '%s'.", p_td.name); | |
912 | return NULL; | |
913 | } | |
914 | ||
915 | boolean Base_Type::BER_decode_isMyMsg(const TTCN_Typedescriptor_t& p_td, | |
916 | const ASN_BER_TLV_t& p_tlv) | |
917 | { | |
918 | if(p_td.ber->n_tags==0 || !p_tlv.isTagComplete) return TRUE; | |
919 | const ASN_Tag_t& tag=p_td.ber->tags[p_td.ber->n_tags-1]; | |
920 | return (tag.tagclass==p_tlv.tagclass && tag.tagnumber==p_tlv.tagnumber); | |
921 | } | |
922 | ||
923 | boolean Base_Type::BER_decode_TLV(const TTCN_Typedescriptor_t& p_td, | |
924 | const ASN_BER_TLV_t& p_tlv, | |
925 | unsigned L_form) | |
926 | { | |
927 | BER_chk_descr(p_td); | |
928 | ASN_BER_TLV_t stripped_tlv; | |
929 | BER_decode_strip_tags(*p_td.ber, p_tlv, L_form, stripped_tlv); | |
930 | TTCN_EncDec_ErrorContext ec; | |
931 | ec.error_internal | |
932 | ("BER_decode_V() not implemented for type '%s'.", p_td.name); | |
933 | return FALSE; | |
934 | } | |
935 | ||
936 | int Base_Type::RAW_encode(const TTCN_Typedescriptor_t& p_td, | |
937 | RAW_enc_tree&) const | |
938 | { | |
939 | TTCN_error("RAW encoding requested for type '%s'" | |
940 | " which has no RAW encoding method.", p_td.name); | |
941 | return 0; | |
942 | } | |
943 | ||
944 | int Base_Type::TEXT_encode(const TTCN_Typedescriptor_t& p_td, | |
945 | TTCN_Buffer&) const | |
946 | { | |
947 | TTCN_error("TEXT encoding requested for type '%s'" | |
948 | " which has no TEXT encoding method.", p_td.name); | |
949 | return 0; | |
950 | } | |
951 | ||
952 | int Base_Type::TEXT_decode(const TTCN_Typedescriptor_t& p_td, | |
953 | TTCN_Buffer&, Limit_Token_List&, boolean, boolean) | |
954 | { | |
955 | TTCN_error("TEXT decoding requested for type '%s'" | |
956 | " which has no TEXT decoding method.", p_td.name); | |
957 | return 0; | |
958 | } | |
959 | ||
960 | int Base_Type::RAW_decode(const TTCN_Typedescriptor_t& p_td, | |
961 | TTCN_Buffer&, int /* limit */, raw_order_t /* top_bit_ord */, | |
962 | boolean /* no_error */, int /* sel_field */, boolean /* first_call */ ) | |
963 | { | |
964 | TTCN_error("RAW decoding requested for type '%s'" | |
965 | " which has no RAW decoding method.",p_td.name); | |
966 | return 0; | |
967 | } | |
968 | ||
969 | int Base_Type::XER_encode(const XERdescriptor_t& p_td, | |
af710487 | 970 | TTCN_Buffer&, unsigned int, int, embed_values_enc_struct_t*) const |
970ed795 EL |
971 | { |
972 | TTCN_error("XER encoding requested for type '%-.*s' which has no" | |
973 | " XER encoding method.", p_td.namelens[0]-2, p_td.names[0]); | |
974 | return 0; | |
975 | } | |
976 | ||
af710487 | 977 | int Base_Type::XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap&, |
978 | unsigned int, embed_values_dec_struct_t*) { | |
970ed795 EL |
979 | TTCN_error("XER decoding requested for type '%-.*s' which has no" |
980 | " XER decoding method.", p_td.namelens[0]-2, p_td.names[0]); | |
981 | return 0; | |
982 | } | |
983 | ||
984 | int Base_Type::JSON_encode(const TTCN_Typedescriptor_t& p_td, JSON_Tokenizer&) const | |
985 | { | |
986 | TTCN_error("JSON encoding requested for type '%s' which has no" | |
987 | " JSON encoding method.", p_td.name); | |
988 | return 0; | |
989 | } | |
990 | ||
991 | int Base_Type::JSON_decode(const TTCN_Typedescriptor_t& p_td, JSON_Tokenizer&, boolean) | |
992 | { | |
993 | TTCN_error("JSON decoding requested for type '%s' which has no" | |
994 | " JSON decoding method.", p_td.name); | |
995 | return 0; | |
996 | } | |
997 | ||
998 | boolean Base_Type::can_start(const char *name, const char *uri, | |
999 | XERdescriptor_t const& xd, unsigned int flavor) | |
1000 | { | |
1001 | boolean e_xer = is_exer(flavor); | |
1002 | // Check the name. If EXER, check the namespace too. | |
1003 | return check_name(name, xd, e_xer) && (!e_xer || check_namespace(uri, xd)); | |
1004 | } | |
1005 | ||
1006 | char ** Base_Type::collect_ns(const XERdescriptor_t& p_td, size_t& num, bool& def_ns) const | |
1007 | { | |
1008 | def_ns = false; | |
1009 | char *tmp = NULL; | |
1010 | if (p_td.my_module != 0 && p_td.ns_index != -1 | |
1011 | && !(p_td.xer_bits & FORM_UNQUALIFIED)) { | |
1012 | const namespace_t *my_ns = p_td.my_module->get_ns(p_td.ns_index); | |
1013 | if (!*my_ns->px) def_ns = true; | |
1014 | tmp = mprintf(" xmlns%s%s='%s'", | |
1015 | ((*my_ns->px) ? ":" : ""), my_ns->px, | |
1016 | my_ns->ns | |
1017 | ); | |
1018 | } | |
1019 | // The above may throw, but then nothing was allocated. | |
1020 | if (tmp != NULL) { | |
1021 | num = 1; | |
1022 | char **retval = (char**)Malloc(sizeof(char*)); | |
1023 | *retval = tmp; | |
1024 | return retval; | |
1025 | } | |
1026 | else { | |
1027 | num = 0; | |
1028 | return NULL; | |
1029 | } | |
1030 | } | |
1031 | ||
1032 | void Base_Type::merge_ns(char **&collected_ns, size_t& num_collected, | |
1033 | char **new_namespaces, size_t num_new) | |
1034 | { | |
1035 | ||
1036 | for (size_t cur_ns = 0; cur_ns < num_new; ++cur_ns) { | |
1037 | for (size_t cur_coll = 0; cur_coll < num_collected; ++cur_coll) { | |
1038 | if (!strcmp(new_namespaces[cur_ns], collected_ns[cur_coll])) { | |
1039 | // same, drop it | |
1040 | Free(new_namespaces[cur_ns]); | |
1041 | new_namespaces[cur_ns] = NULL; | |
1042 | break; | |
1043 | } | |
1044 | } | |
1045 | ||
1046 | if (new_namespaces[cur_ns]) { // still there | |
1047 | collected_ns = (char**)Realloc(collected_ns, sizeof(char*) * ++num_collected); | |
1048 | collected_ns[num_collected-1] = new_namespaces[cur_ns]; | |
1049 | } | |
1050 | } | |
1051 | Free(new_namespaces); | |
1052 | new_namespaces = 0; | |
1053 | } | |
1054 | ||
1055 | ///////////////////////////////////////////////////////////// | |
1056 | ||
1057 | TTCN_Type_list::~TTCN_Type_list() | |
1058 | { | |
1059 | Free(types); | |
1060 | } | |
1061 | ||
1062 | void TTCN_Type_list::push(const Base_Type *p_type) | |
1063 | { | |
1064 | types=(const Base_Type**)Realloc(types, ++n_types*sizeof(*types)); | |
1065 | types[n_types-1]=p_type; | |
1066 | } | |
1067 | ||
1068 | const Base_Type* TTCN_Type_list::pop() | |
1069 | { | |
1070 | if(!n_types) | |
1071 | TTCN_EncDec_ErrorContext::error_internal | |
1072 | ("TTCN_Type_list::pop(): List is empty."); | |
1073 | const Base_Type *t; | |
1074 | t=types[--n_types]; | |
1075 | types=(const Base_Type**)Realloc(types, n_types*sizeof(*types)); | |
1076 | return t; | |
1077 | } | |
1078 | ||
1079 | const Base_Type* TTCN_Type_list::get_nth(size_t pos) const | |
1080 | { | |
1081 | if(pos==0) return types[0]; | |
1082 | if(pos>n_types) | |
1083 | TTCN_EncDec_ErrorContext::error_internal | |
1084 | ("TTCN_Type_list::get_nth(%lu): Out of range.", (unsigned long) pos); | |
1085 | return types[n_types-pos]; | |
1086 | } | |
1087 | ||
1088 | const TTCN_Typedescriptor_t BOOLEAN_descr_={"BOOLEAN", &BOOLEAN_ber_, | |
1089 | &BOOLEAN_raw_, &BOOLEAN_text_, &BOOLEAN_xer_, &BOOLEAN_json_, TTCN_Typedescriptor_t::DONTCARE}; | |
1090 | ||
1091 | const TTCN_Typedescriptor_t INTEGER_descr_={"INTEGER", &INTEGER_ber_, | |
1092 | &INTEGER_raw_, &INTEGER_text_, &INTEGER_xer_, &INTEGER_json_, TTCN_Typedescriptor_t::DONTCARE}; | |
1093 | ||
1094 | const TTCN_Typedescriptor_t FLOAT_descr_={"REAL", &FLOAT_ber_, &FLOAT_raw_, | |
1095 | NULL, &FLOAT_xer_, &FLOAT_json_, TTCN_Typedescriptor_t::DONTCARE}; | |
1096 | ||
1097 | const TTCN_Typedescriptor_t VERDICTTYPE_descr_={"verdicttype", NULL, NULL, | |
1098 | NULL, &VERDICTTYPE_xer_, &VERDICTTYPE_json_, TTCN_Typedescriptor_t::DONTCARE}; | |
1099 | ||
1100 | const TTCN_Typedescriptor_t OBJID_descr_={"OBJECT IDENTIFIER", &OBJID_ber_, | |
af710487 | 1101 | NULL, NULL, &OBJID_xer_, &OBJID_json_, TTCN_Typedescriptor_t::OBJID}; |
970ed795 EL |
1102 | |
1103 | const TTCN_Typedescriptor_t BITSTRING_descr_={"BIT STRING", &BITSTRING_ber_, | |
1104 | &BITSTRING_raw_, NULL, &BITSTRING_xer_, &BITSTRING_json_, TTCN_Typedescriptor_t::DONTCARE}; | |
1105 | ||
1106 | const TTCN_Typedescriptor_t HEXSTRING_descr_={"hexstring", NULL, | |
1107 | &HEXSTRING_raw_, NULL, &HEXSTRING_xer_, &HEXSTRING_json_, TTCN_Typedescriptor_t::DONTCARE}; | |
1108 | ||
1109 | const TTCN_Typedescriptor_t OCTETSTRING_descr_={"OCTET STRING", | |
1110 | &OCTETSTRING_ber_, &OCTETSTRING_raw_, &OCTETSTRING_text_, &OCTETSTRING_xer_, &OCTETSTRING_json_, TTCN_Typedescriptor_t::DONTCARE}; | |
1111 | ||
1112 | const TTCN_Typedescriptor_t CHARSTRING_descr_={"charstring", NULL, | |
1113 | &CHARSTRING_raw_, &CHARSTRING_text_, &CHARSTRING_xer_, &CHARSTRING_json_, TTCN_Typedescriptor_t::DONTCARE}; | |
1114 | ||
1115 | const TTCN_Typedescriptor_t UNIVERSAL_CHARSTRING_descr_={"universal charstring", | |
1116 | NULL, NULL, NULL, &UNIVERSAL_CHARSTRING_xer_, &UNIVERSAL_CHARSTRING_json_, TTCN_Typedescriptor_t::DONTCARE}; | |
1117 | ||
1118 | const TTCN_Typedescriptor_t COMPONENT_descr_={"component", NULL, NULL, NULL, | |
1119 | NULL, NULL, TTCN_Typedescriptor_t::DONTCARE}; | |
1120 | ||
1121 | const TTCN_Typedescriptor_t DEFAULT_descr_={"default", NULL, NULL, NULL, | |
1122 | NULL, NULL, TTCN_Typedescriptor_t::DONTCARE}; | |
1123 | ||
1124 | const TTCN_Typedescriptor_t ASN_NULL_descr_={"NULL", &ASN_NULL_ber_, NULL, | |
af710487 | 1125 | NULL, &ASN_NULL_xer_, &ASN_NULL_json_, TTCN_Typedescriptor_t::DONTCARE}; |
970ed795 EL |
1126 | |
1127 | const TTCN_Typedescriptor_t ASN_ANY_descr_={"ANY", &ASN_ANY_ber_, NULL, | |
af710487 | 1128 | NULL, NULL, &ASN_ANY_json_, TTCN_Typedescriptor_t::DONTCARE}; |
970ed795 EL |
1129 | |
1130 | const TTCN_Typedescriptor_t EXTERNAL_descr_={"EXTERNAL", &EXTERNAL_ber_, NULL, | |
1131 | NULL, &EXTERNAL_xer_, NULL, TTCN_Typedescriptor_t::DONTCARE}; | |
1132 | ||
1133 | const TTCN_Typedescriptor_t EMBEDDED_PDV_descr_={"EMBEDDED PDV", | |
1134 | &EMBEDDED_PDV_ber_, NULL, NULL, &EMBEDDED_PDV_xer_, NULL, TTCN_Typedescriptor_t::DONTCARE}; | |
1135 | ||
1136 | const TTCN_Typedescriptor_t CHARACTER_STRING_descr_={"CHARACTER STRING", | |
1137 | &CHARACTER_STRING_ber_, NULL, NULL, &CHARACTER_STRING_xer_, NULL, TTCN_Typedescriptor_t::DONTCARE}; | |
1138 | ||
1139 | const TTCN_Typedescriptor_t ObjectDescriptor_descr_={"ObjectDescriptor", | |
1140 | &ObjectDescriptor_ber_, NULL, NULL, NULL, NULL, TTCN_Typedescriptor_t::GRAPHICSTRING}; | |
1141 | ||
1142 | const TTCN_Typedescriptor_t UTF8String_descr_={"UTF8String", &UTF8String_ber_, | |
1143 | NULL, NULL, &UTF8String_xer_, NULL, TTCN_Typedescriptor_t::UTF8STRING}; | |
1144 | ||
1145 | const TTCN_Typedescriptor_t ASN_ROID_descr_={"RELATIVE-OID", &ASN_ROID_ber_, | |
af710487 | 1146 | NULL, NULL, &ASN_ROID_xer_, &ASN_ROID_json_, TTCN_Typedescriptor_t::ROID}; |
970ed795 EL |
1147 | |
1148 | const TTCN_Typedescriptor_t NumericString_descr_={"NumericString", | |
1149 | &NumericString_ber_, NULL, NULL, &NumericString_xer_, NULL, TTCN_Typedescriptor_t::DONTCARE}; | |
1150 | ||
1151 | const TTCN_Typedescriptor_t PrintableString_descr_={"PrintableString", | |
1152 | &PrintableString_ber_, NULL, NULL, &PrintableString_xer_, NULL, TTCN_Typedescriptor_t::DONTCARE}; | |
1153 | ||
1154 | const TTCN_Typedescriptor_t TeletexString_descr_={"TeletexString", | |
1155 | &TeletexString_ber_, NULL, NULL, &TeletexString_xer_, NULL, TTCN_Typedescriptor_t::TELETEXSTRING}; | |
1156 | const TTCN_Typedescriptor_t& T61String_descr_=TeletexString_descr_; | |
1157 | ||
1158 | const TTCN_Typedescriptor_t VideotexString_descr_={"VideotexString", | |
1159 | &VideotexString_ber_, NULL, NULL, &VideotexString_xer_, NULL, TTCN_Typedescriptor_t::VIDEOTEXSTRING}; | |
1160 | ||
1161 | const TTCN_Typedescriptor_t IA5String_descr_={"IA5String", &IA5String_ber_, | |
1162 | NULL, NULL, &IA5String_xer_, NULL, TTCN_Typedescriptor_t::DONTCARE}; | |
1163 | ||
1164 | const TTCN_Typedescriptor_t ASN_GeneralizedTime_descr_={"GeneralizedTime", | |
1165 | &ASN_GeneralizedTime_ber_, NULL, NULL, NULL, NULL, TTCN_Typedescriptor_t::DONTCARE}; | |
1166 | ||
1167 | const TTCN_Typedescriptor_t ASN_UTCTime_descr_={"UTCTime", &ASN_UTCTime_ber_, | |
1168 | NULL, NULL, NULL, NULL, TTCN_Typedescriptor_t::DONTCARE}; | |
1169 | ||
1170 | const TTCN_Typedescriptor_t GraphicString_descr_={"GraphicString", | |
1171 | &GraphicString_ber_, NULL, NULL, &GraphicString_xer_, NULL, TTCN_Typedescriptor_t::GRAPHICSTRING}; | |
1172 | ||
1173 | const TTCN_Typedescriptor_t VisibleString_descr_={"VisibleString", | |
1174 | &VisibleString_ber_, NULL, NULL, &VisibleString_xer_, NULL, TTCN_Typedescriptor_t::DONTCARE}; | |
1175 | const TTCN_Typedescriptor_t& ISO646String_descr_=VisibleString_descr_; | |
1176 | ||
1177 | const TTCN_Typedescriptor_t GeneralString_descr_={"GeneralString", | |
1178 | &GeneralString_ber_, NULL, NULL, &GeneralString_xer_, NULL, TTCN_Typedescriptor_t::GENERALSTRING}; | |
1179 | ||
1180 | const TTCN_Typedescriptor_t UniversalString_descr_={"UniversalString", | |
1181 | &UniversalString_ber_, NULL, NULL, &UniversalString_xer_, NULL, TTCN_Typedescriptor_t::UNIVERSALSTRING}; | |
1182 | ||
1183 | const TTCN_Typedescriptor_t BMPString_descr_={"BMPString", &BMPString_ber_, | |
1184 | NULL, NULL, &BMPString_xer_, NULL, TTCN_Typedescriptor_t::BMPSTRING}; | |
1185 | ||
1186 |