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