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 ///////////////////////////////////////////////////////////////////////////////
17 #include "Optional.hh"
19 #include "Param_Types.hh"
24 #include "Charstring.hh"
26 #include "XmlReader.hh"
28 #include <openssl/bn.h>
29 #include <openssl/crypto.h>
31 #include "../common/dbgnew.hh"
33 #if defined(__GNUC__) && __GNUC__ >= 3
34 // To provide prediction information for the compiler.
35 // Borrowed from /usr/src/linux/include/linux/compiler.h.
36 #define likely(x) __builtin_expect(!!(x), 1)
37 #define unlikely(x) __builtin_expect(!!(x), 0)
40 #define unlikely(x) (x)
43 static const Token_Match
integer_value_match("^([\t ]*-?[0-9]+).*$", TRUE
);
45 int_val_t
INTEGER::get_val() const
47 if (likely(native_flag
)) return int_val_t(val
.native
);
48 else return int_val_t(BN_dup(val
.openssl
));
51 void INTEGER::set_val(const int_val_t
& other_value
)
55 native_flag
= other_value
.native_flag
;
56 if (likely(native_flag
)) val
.native
= other_value
.val
.native
;
57 else val
.openssl
= BN_dup(other_value
.val
.openssl
);
66 INTEGER::INTEGER(int other_value
)
70 val
.native
= other_value
;
73 INTEGER::INTEGER(const INTEGER
& other_value
)
74 : Base_Type(other_value
)
76 other_value
.must_bound("Copying an unbound integer value.");
78 native_flag
= other_value
.native_flag
;
79 if (likely(native_flag
)) val
.native
= other_value
.val
.native
;
80 else val
.openssl
= BN_dup(other_value
.val
.openssl
);
83 /// Return 0 if fail, 1 on success
84 int INTEGER::from_string(const char *s
) {
85 BIGNUM
*other_value_int
= NULL
;
86 if (BN_dec2bn(&other_value_int
, s
+ (*s
== '+')))
89 if (BN_num_bits(other_value_int
) > (int)sizeof(int) * 8 - 1) {
91 val
.openssl
= other_value_int
;
94 val
.native
= string2RInt(s
);
95 BN_free(other_value_int
);
102 INTEGER::INTEGER(const char *other_value
)
104 if (unlikely(!other_value
))
105 TTCN_error("Unexpected error when converting `%s' to integer",
108 if (!from_string(other_value
)) TTCN_error(
109 "Unexpected error when converting `%s' to integer", other_value
);
112 // For internal use only. It's not part of the public interface.
113 INTEGER::INTEGER(BIGNUM
*other_value
)
115 if (unlikely(!other_value
))
116 TTCN_error("Unexpected error when initializing an integer");
119 val
.openssl
= other_value
;
124 if (unlikely(!native_flag
)) BN_free(val
.openssl
);
127 void INTEGER::clean_up()
129 if (!bound_flag
) return;
130 if (unlikely(!native_flag
)) BN_free(val
.openssl
);
134 INTEGER
& INTEGER::operator=(int other_value
)
139 val
.native
= other_value
;
143 INTEGER
& INTEGER::operator=(const INTEGER
& other_value
)
145 if (this == &other_value
)
147 other_value
.must_bound("Assignment of an unbound integer value.");
150 native_flag
= other_value
.native_flag
;
151 if (likely(native_flag
)) val
.native
= other_value
.val
.native
;
152 else val
.openssl
= BN_dup(other_value
.val
.openssl
);
156 // A bit more specific than operator+().
157 INTEGER
& INTEGER::operator++()
159 must_bound("Unbound integer operand of unary increment operator.");
160 if (likely(native_flag
)) {
161 unsigned int result_u
= val
.native
+ 1;
162 int result
= val
.native
+ 1;
163 if (unlikely((static_cast<int>(result_u
) != result
) || (val
.native
> 0 && result
< 0))) {
164 BIGNUM
*val_openssl
= to_openssl(val
.native
);
165 BIGNUM
*one
= BN_new();
167 BN_add(val_openssl
, val_openssl
, one
);
170 val
.openssl
= val_openssl
;
175 BIGNUM
*one
= BN_new();
177 BN_add(val
.openssl
, val
.openssl
, one
);
183 // A bit more specific than operator-().
184 INTEGER
& INTEGER::operator--()
186 must_bound("Unbound integer operand of unary decrement operator.");
187 if (likely(native_flag
)) {
188 if (unlikely(val
.native
== INT_MIN
)) {
189 BIGNUM
*val_openssl
= to_openssl(val
.native
);
190 BIGNUM
*one
= BN_new();
192 BN_sub(val_openssl
, val_openssl
, one
);
195 val
.openssl
= val_openssl
;
200 BIGNUM
*one
= BN_new();
202 BN_sub(val
.openssl
, val
.openssl
, one
);
208 INTEGER
INTEGER::operator+() const
210 must_bound("Unbound integer operand of unary + operator.");
214 INTEGER
INTEGER::operator-() const
216 must_bound("Unbound integer operand of unary - operator (negation).");
217 if (likely(native_flag
)) {
218 if (unlikely(val
.native
== INT_MIN
)) {
219 BIGNUM
*result
= to_openssl(INT_MIN
);
220 BN_set_negative(result
, 0);
221 return INTEGER(result
);
223 return INTEGER(-val
.native
);
226 BIGNUM
*int_max_plus_one
= to_openssl(INT_MIN
);
227 BN_set_negative(int_max_plus_one
, 0);
228 int cmp
= BN_cmp(val
.openssl
, int_max_plus_one
);
229 BN_free(int_max_plus_one
);
230 if (unlikely(cmp
== 0)) {
231 return INTEGER(INT_MIN
);
233 BIGNUM
*result
= BN_dup(val
.openssl
);
234 BN_set_negative(result
, !BN_is_negative(result
));
235 return INTEGER(result
);
240 INTEGER
INTEGER::operator+(int other_value
) const
242 must_bound("Unbound left operand of integer addition.");
243 // Don't call out if slow. Implement this specific case right here.
244 return *this + INTEGER(other_value
);
247 INTEGER
INTEGER::operator+(const INTEGER
& other_value
) const
249 must_bound("Unbound left operand of integer addition.");
250 other_value
.must_bound("Unbound right operand of integer addition.");
251 // *this + other_value = *this add other_value
252 // *this + -other_value = *this sub other_value
253 // -*this + other_value = other_value sub *this
254 // -*this + -other_value = -(*this add other_value)
255 // Use only inline functions and BN_* directly. Call out for operator- in
257 boolean this_neg
= native_flag
? (val
.native
< 0)
258 : BN_is_negative(val
.openssl
);
259 boolean other_value_neg
= other_value
.native_flag
260 ? (other_value
.val
.native
< 0) : BN_is_negative(other_value
.val
.openssl
);
261 boolean result_neg
= this_neg
&& other_value_neg
;
262 if (!this_neg
&& other_value_neg
) return operator-(-other_value
);
263 if (this_neg
&& !other_value_neg
) return other_value
.operator-(-(*this));
264 if (likely(native_flag
)) {
265 if (likely(other_value
.native_flag
)) {
266 unsigned int result_u
= val
.native
+ other_value
.val
.native
;
267 int result
= val
.native
+ other_value
.val
.native
;
268 if ((static_cast<int>(result_u
) != result
) || (!result_neg
&&
269 result
< 0) || (result_neg
&& result
> 0)) {
270 // We can safely assume that the sum of two non-negative int values
271 // fit in an unsigned int. limits.h says:
272 // # define INT_MAX 2147483647
273 // # define UINT_MAX 4294967295
274 BIGNUM
*this_int
= to_openssl(val
.native
);
275 BIGNUM
*other_val_int
= to_openssl(other_value
.val
.native
);
276 BN_add(this_int
, this_int
, other_val_int
);
277 BN_free(other_val_int
);
278 return INTEGER(this_int
);
280 return INTEGER(result
);
283 // int (>= 0) + BIGNUM == BIGNUM.
284 BIGNUM
*this_int
= to_openssl(val
.native
);
285 BN_add(this_int
, this_int
, other_value
.val
.openssl
);
286 return INTEGER(this_int
);
289 // BIGNUM + int (>= 0) == BIGNUM.
290 BIGNUM
*result
= BN_new();
291 BIGNUM
*other_value_int
;
292 other_value_int
= other_value
.native_flag
293 ? to_openssl(other_value
.val
.native
) : other_value
.val
.openssl
;
294 BN_add(result
, val
.openssl
, other_value_int
);
295 if (likely(other_value
.native_flag
)) BN_free(other_value_int
);
296 return INTEGER(result
);
300 INTEGER
INTEGER::operator-(int other_value
) const
302 must_bound("Unbound left operand of integer subtraction.");
303 return *this - INTEGER(other_value
);
306 INTEGER
INTEGER::operator-(const INTEGER
& other_value
) const
308 must_bound("Unbound left operand of integer subtraction.");
309 other_value
.must_bound("Unbound right operand of integer subtraction.");
310 // *this - other_value = *this sub other_value
311 // -*this - other_value = -(*this add other_value)
312 // *this - -other_value = *this add other_value
313 // -*this - -other_value = -*this add other_value = other_value sub *this
314 boolean this_neg
= native_flag
? (val
.native
< 0)
315 : BN_is_negative(val
.openssl
);
316 boolean other_value_neg
= other_value
.native_flag
317 ? (other_value
.val
.native
< 0) : BN_is_negative(other_value
.val
.openssl
);
318 if (!this_neg
&& other_value_neg
) return operator+(-other_value
);
319 if (this_neg
&& !other_value_neg
) return -other_value
.operator+(-(*this));
320 if (likely(native_flag
)) {
321 if (likely(other_value
.native_flag
)) {
322 // Since both operands are non-negative the most negative result of a
323 // subtraction can be -INT_MAX and according to limits.h:
324 // # define INT_MIN (-INT_MAX - 1)
325 return INTEGER(val
.native
- other_value
.val
.native
);
327 BIGNUM
*this_int
= to_openssl(val
.native
);
328 BN_sub(this_int
, this_int
, other_value
.val
.openssl
);
329 // The result can be small enough to fit in int. Back conversion is a
330 // costly operation using strings all the time.
331 if (BN_num_bits(this_int
) <= (int)sizeof(int) * 8 - 1) {
332 char *result_str
= BN_bn2dec(this_int
);
333 RInt result
= string2RInt(result_str
);
334 OPENSSL_free(result_str
);
336 return INTEGER(result
);
338 return INTEGER(this_int
);
342 BIGNUM
*result
= BN_new();
343 BIGNUM
*other_value_int
= other_value
.native_flag
?
344 to_openssl(other_value
.val
.native
) : other_value
.val
.openssl
;
345 BN_sub(result
, val
.openssl
, other_value_int
);
346 if (other_value
.native_flag
) BN_free(other_value_int
);
347 if (BN_num_bits(result
) <= (int)sizeof(int) * 8 - 1) {
348 char *result_str
= BN_bn2dec(result
);
349 RInt result_int
= string2RInt(result_str
);
350 OPENSSL_free(result_str
);
352 return INTEGER(result_int
);
354 return INTEGER(result
);
359 INTEGER
INTEGER::operator*(int other_value
) const
361 must_bound("Unbound left operand of integer multiplication.");
362 return *this * INTEGER(other_value
);
365 INTEGER
INTEGER::operator*(const INTEGER
& other_value
) const
367 must_bound("Unbound left operand of integer multiplication.");
368 other_value
.must_bound("Unbound right operand of integer multiplication.");
369 if ((native_flag
&& val
.native
== 0) || (other_value
.native_flag
&&
370 other_value
.val
.native
== 0)) return INTEGER((int)0);
371 if (likely(native_flag
)) {
372 if (likely(other_value
.native_flag
)) {
374 if (likely(abs(val
.native
) < 32768 && abs(other_value
.val
.native
) < 32768)) {
375 return INTEGER(val
.native
* other_value
.val
.native
);
377 BIGNUM
*this_int
= to_openssl(val
.native
);
378 BIGNUM
*other_value_int
= to_openssl(other_value
.val
.native
);
379 BN_CTX
*ctx
= BN_CTX_new();
381 BN_mul(this_int
, this_int
, other_value_int
, ctx
);
383 BN_free(other_value_int
);
384 if (BN_num_bits(this_int
) < (int)sizeof(int) * 8) {
386 return INTEGER(val
.native
* other_value
.val
.native
);
388 return INTEGER(this_int
);
392 BIGNUM
*this_int
= to_openssl(val
.native
);
393 BN_CTX
*ctx
= BN_CTX_new();
395 BN_mul(this_int
, this_int
, other_value
.val
.openssl
, ctx
);
397 return INTEGER(this_int
);
400 BIGNUM
*result
= BN_new();
401 BIGNUM
*other_value_int
= NULL
;
402 BN_CTX
*ctx
= BN_CTX_new();
404 other_value_int
= other_value
.native_flag
405 ? to_openssl(other_value
.val
.native
) : other_value
.val
.openssl
;
406 BN_mul(result
, val
.openssl
, other_value_int
, ctx
);
408 if (likely(other_value
.native_flag
)) BN_free(other_value_int
);
409 return INTEGER(result
);
413 INTEGER
INTEGER::operator/(int other_value
) const
415 must_bound("Unbound left operand of integer division.");
416 if (other_value
== 0) TTCN_error("Integer division by zero.");
417 return *this / INTEGER(other_value
);
420 INTEGER
INTEGER::operator/(const INTEGER
& other_value
) const
422 must_bound("Unbound left operand of integer division.");
423 other_value
.must_bound("Unbound right operand of integer division.");
424 if (other_value
== 0) TTCN_error("Integer division by zero.");
425 if (native_flag
&& val
.native
== 0) return INTEGER((int)0);
426 if (likely(native_flag
)) {
427 if (likely(other_value
.native_flag
)) {
428 return INTEGER(val
.native
/ other_value
.val
.native
);
430 BIGNUM
*this_int
= to_openssl(val
.native
);
431 BN_CTX
*ctx
= BN_CTX_new();
433 BN_div(this_int
, NULL
, this_int
, other_value
.val
.openssl
, ctx
);
435 if (BN_num_bits(this_int
) <= (int)sizeof(int) * 8 - 1) {
436 char *result_str
= BN_bn2dec(this_int
);
437 RInt result
= string2RInt(result_str
);
438 OPENSSL_free(result_str
);
440 return INTEGER(result
);
442 return INTEGER(this_int
);
446 BIGNUM
*result
= BN_new();
447 BIGNUM
*other_value_int
= NULL
;
448 BN_CTX
*ctx
= BN_CTX_new();
450 other_value_int
= other_value
.native_flag
451 ? to_openssl(other_value
.val
.native
) : other_value
.val
.openssl
;
452 BN_div(result
, NULL
, val
.openssl
, other_value_int
, ctx
);
453 if (likely(other_value
.native_flag
)) BN_free(other_value_int
);
455 if (BN_num_bits(result
) <= (int)sizeof(int) * 8 - 1) {
456 char *result_str
= BN_bn2dec(result
);
457 RInt result_i
= string2RInt(result_str
);
458 OPENSSL_free(result_str
);
460 return INTEGER(result_i
);
462 return INTEGER(result
);
467 boolean
INTEGER::operator==(int other_value
) const
469 must_bound("Unbound left operand of integer comparison.");
470 if (likely(native_flag
)) {
471 return val
.native
== other_value
;
473 BIGNUM
*other_value_int
= to_openssl(other_value
);
474 int equal
= BN_cmp(val
.openssl
, other_value_int
);
475 BN_free(other_value_int
);
480 boolean
INTEGER::operator==(const INTEGER
& other_value
) const
482 must_bound("Unbound left operand of integer comparison.");
483 other_value
.must_bound("Unbound right operand of integer comparison.");
484 if (likely(native_flag
)) {
485 if (likely(other_value
.native_flag
)) {
486 return val
.native
== other_value
.val
.native
;
488 BIGNUM
*this_int
= to_openssl(val
.native
);
489 int equal
= BN_cmp(this_int
, other_value
.val
.openssl
);
494 if (likely(other_value
.native_flag
)) {
495 BIGNUM
*other_value_int
= to_openssl(other_value
.val
.native
);
496 int equal
= BN_cmp(val
.openssl
, other_value_int
);
497 BN_free(other_value_int
);
500 return BN_cmp(val
.openssl
, other_value
.val
.openssl
) == 0;
505 boolean
INTEGER::operator<(int other_value
) const
507 must_bound("Unbound left operand of integer comparison.");
508 return *this < INTEGER(other_value
);
511 boolean
INTEGER::operator<(const INTEGER
& other_value
) const
513 must_bound("Unbound left operand of integer comparison.");
514 other_value
.must_bound("Unbound right operand of integer comparison.");
515 if (likely(native_flag
)) {
516 if (likely(other_value
.native_flag
)) {
517 return val
.native
< other_value
.val
.native
;
519 BIGNUM
*this_int
= to_openssl(val
.native
);
520 int equal
= BN_cmp(this_int
, other_value
.val
.openssl
);
525 if (likely(other_value
.native_flag
)) {
526 BIGNUM
*other_value_int
= to_openssl(other_value
.val
.native
);
527 int equal
= BN_cmp(val
.openssl
, other_value_int
);
528 BN_free(other_value_int
);
531 return BN_cmp(val
.openssl
, other_value
.val
.openssl
) == -1;
536 boolean
INTEGER::operator>(int other_value
) const
538 must_bound("Unbound left operand of integer comparison.");
539 return *this > INTEGER(other_value
);
542 boolean
INTEGER::operator>(const INTEGER
& other_value
) const
544 // A simple call to operator< and operator== would be much simplier.
545 must_bound("Unbound left operand of integer comparison.");
546 other_value
.must_bound("Unbound right operand of integer comparison.");
547 if (likely(native_flag
)) {
548 if (likely(other_value
.native_flag
)) {
549 return val
.native
> other_value
.val
.native
;
551 BIGNUM
*this_int
= to_openssl(val
.native
);
552 int equal
= BN_cmp(this_int
, other_value
.val
.openssl
);
557 if (likely(other_value
.native_flag
)) {
558 BIGNUM
*other_value_int
= to_openssl(other_value
.val
.native
);
559 int equal
= BN_cmp(val
.openssl
, other_value_int
);
560 BN_free(other_value_int
);
563 return BN_cmp(val
.openssl
, other_value
.val
.openssl
) == 1;
568 INTEGER::operator int() const
570 must_bound("Using the value of an unbound integer variable.");
571 if (unlikely(!native_flag
))
572 TTCN_error("Invalid conversion of a large integer value");
576 // To avoid ambiguity we have a separate function to convert our INTEGER
577 // object to long long.
578 long long int INTEGER::get_long_long_val() const
580 must_bound("Using the value of an unbound integer variable.");
581 if (likely(native_flag
)) return val
.native
;
582 size_t slot_size
= sizeof(BN_ULONG
);
583 bool is_negative
= BN_is_negative(val
.openssl
);
584 long long int ret_val
= 0;
585 if (unlikely(val
.openssl
->top
== 0)) return 0;
586 // It feels so bad accessing a BIGNUM directly, but faster than string
588 else if (likely(val
.openssl
->top
== 1))
589 return !is_negative
? val
.openssl
->d
[0] : -val
.openssl
->d
[0];
590 ret_val
= val
.openssl
->d
[val
.openssl
->top
- 1];
591 // From now, shift by 8.
592 for (int i
= val
.openssl
->top
- 2; i
>= 0; i
--) {
593 for (int j
= slot_size
- 1; j
>= 0; j
--) {
594 unsigned char tmp
= (val
.openssl
->d
[i
] >> 8 * j
) & 0xff;
599 return !is_negative
? ret_val
: -ret_val
;
602 void INTEGER::set_long_long_val(long long int other_value
)
606 // Seems to be a native. It's very strange if someone calls this with a
607 // small number. A simple assignment should be used for such values.
608 if (unlikely((RInt
)other_value
== other_value
)) {
610 val
.native
= other_value
;
614 val
.openssl
= BN_new();
616 BN_zero(val
.openssl
);
617 bool is_negative
= other_value
< 0;
618 unsigned long long int tmp
= !is_negative
? other_value
: -other_value
;
619 for (int i
= sizeof(long long int) - 1; i
>= 0; i
--) {
620 BN_add_word(val
.openssl
, (tmp
>> 8 * i
) & 0xff);
621 if (i
) BN_lshift(val
.openssl
, val
.openssl
, 8);
623 BN_set_negative(val
.openssl
, is_negative
? 1 : 0);
626 void INTEGER::log() const
628 if (likely(bound_flag
)) {
629 if (likely(native_flag
)) {
630 TTCN_Logger::log_event("%d", val
.native
);
632 char *tmp
= BN_bn2dec(val
.openssl
);
633 TTCN_Logger::log_event("%s", tmp
);
637 TTCN_Logger::log_event_unbound();
641 void INTEGER::set_param(Module_Param
& param
)
643 param
.basic_check(Module_Param::BC_VALUE
, "integer value");
644 if (param
.get_type()!=Module_Param::MP_Integer
) param
.type_error("integer value");
647 const int_val_t
* const int_val
= param
.get_integer();
648 native_flag
= int_val
->is_native();
649 if (likely(native_flag
)){
650 val
.native
= int_val
->get_val();
652 val
.openssl
= BN_dup(int_val
->get_val_openssl());
656 void INTEGER::encode_text(Text_Buf
& text_buf
) const
658 must_bound("Text encoder: Encoding an unbound integer value.");
659 if (likely(native_flag
)) {
660 text_buf
.push_int(val
.native
);
662 int_val_t
*tmp
= new int_val_t(BN_dup(val
.openssl
));
663 text_buf
.push_int(*tmp
);
668 void INTEGER::decode_text(Text_Buf
& text_buf
)
672 int_val_t
tmp(text_buf
.pull_int());
673 if (likely(tmp
.native_flag
)) {
675 val
.native
= tmp
.get_val();
678 val
.openssl
= BN_dup(tmp
.get_val_openssl());
682 void INTEGER::encode(const TTCN_Typedescriptor_t
& p_td
, TTCN_Buffer
& p_buf
,
683 TTCN_EncDec::coding_t p_coding
, ...) const
686 va_start(pvar
, p_coding
);
688 case TTCN_EncDec::CT_BER
: {
689 TTCN_EncDec_ErrorContext
ec("While BER-encoding type '%s': ", p_td
.name
);
690 unsigned BER_coding
=va_arg(pvar
, unsigned);
691 BER_encode_chk_coding(BER_coding
);
692 ASN_BER_TLV_t
*tlv
=BER_encode_TLV(p_td
, BER_coding
);
693 tlv
->put_in_buffer(p_buf
);
694 ASN_BER_TLV_t::destruct(tlv
);
696 case TTCN_EncDec::CT_RAW
: {
697 TTCN_EncDec_ErrorContext
ec("While RAW-encoding type '%s': ", p_td
.name
);
699 TTCN_EncDec_ErrorContext::error_internal
700 ("No RAW descriptor available for type '%s'.", p_td
.name
);
704 RAW_enc_tree
root(TRUE
,NULL
,&rp
,1,p_td
.raw
);
705 RAW_encode(p_td
, root
);
706 root
.put_to_buf(p_buf
);
708 case TTCN_EncDec::CT_TEXT
: {
709 TTCN_EncDec_ErrorContext
ec("While TEXT-encoding type '%s': ", p_td
.name
);
711 TTCN_EncDec_ErrorContext::error_internal
712 ("No TEXT descriptor available for type '%s'.", p_td
.name
);
713 TEXT_encode(p_td
,p_buf
);
715 case TTCN_EncDec::CT_XER
: {
716 TTCN_EncDec_ErrorContext
ec("While XER-encoding type '%s': ", p_td
.name
);
717 unsigned XER_coding
=va_arg(pvar
, unsigned);
718 XER_encode(*p_td
.xer
, p_buf
, XER_coding
, 0);
720 case TTCN_EncDec::CT_JSON
: {
721 TTCN_EncDec_ErrorContext
ec("While JSON-encoding type '%s': ", p_td
.name
);
723 TTCN_EncDec_ErrorContext::error_internal
724 ("No JSON descriptor available for type '%s'.", p_td
.name
);
725 JSON_Tokenizer
tok(va_arg(pvar
, int) != 0);
726 JSON_encode(p_td
, tok
);
727 p_buf
.put_s(tok
.get_buffer_length(), (const unsigned char*)tok
.get_buffer());
730 TTCN_error("Unknown coding method requested to encode type '%s'",
736 void INTEGER::decode(const TTCN_Typedescriptor_t
& p_td
, TTCN_Buffer
& p_buf
,
737 TTCN_EncDec::coding_t p_coding
, ...)
740 va_start(pvar
, p_coding
);
742 case TTCN_EncDec::CT_BER
: {
743 TTCN_EncDec_ErrorContext
ec("While BER-decoding type '%s': ", p_td
.name
);
744 unsigned L_form
=va_arg(pvar
, unsigned);
746 BER_decode_str2TLV(p_buf
, tlv
, L_form
);
747 BER_decode_TLV(p_td
, tlv
, L_form
);
748 if(tlv
.isComplete
) p_buf
.increase_pos(tlv
.get_len());
750 case TTCN_EncDec::CT_RAW
: {
751 TTCN_EncDec_ErrorContext
ec("While RAW-decoding type '%s': ", p_td
.name
);
753 TTCN_EncDec_ErrorContext::error_internal
754 ("No RAW descriptor available for type '%s'.", p_td
.name
);
756 switch(p_td
.raw
->top_bit_order
){
764 if(RAW_decode(p_td
, p_buf
, p_buf
.get_len()*8, order
)<0)
765 ec
.error(TTCN_EncDec::ET_INCOMPL_MSG
,
766 "Can not decode type '%s', because invalid or incomplete"
767 " message was received"
770 case TTCN_EncDec::CT_TEXT
: {
771 Limit_Token_List limit
;
772 TTCN_EncDec_ErrorContext
ec("While TEXT-decoding type '%s': ", p_td
.name
);
774 TTCN_EncDec_ErrorContext::error_internal
775 ("No TEXT descriptor available for type '%s'.", p_td
.name
);
776 const unsigned char *b
=p_buf
.get_data();
777 if(b
[p_buf
.get_len()-1]!='\0'){
778 p_buf
.set_pos(p_buf
.get_len());
779 p_buf
.put_zero(8,ORDER_LSB
);
782 if(TEXT_decode(p_td
,p_buf
,limit
)<0)
783 ec
.error(TTCN_EncDec::ET_INCOMPL_MSG
,
784 "Can not decode type '%s', because invalid or incomplete"
785 " message was received"
788 case TTCN_EncDec::CT_XER
: {
789 TTCN_EncDec_ErrorContext
ec("While XER-decoding type '%s': ", p_td
.name
);
790 unsigned XER_coding
=va_arg(pvar
, unsigned);
791 XmlReaderWrap
reader(p_buf
);
792 for (int success
= reader
.Read(); success
==1; success
=reader
.Read()) {
793 int type
= reader
.NodeType();
794 if (type
==XML_READER_TYPE_ELEMENT
)
797 XER_decode(*p_td
.xer
, reader
, XER_coding
);
798 size_t bytes
= reader
.ByteConsumed();
799 p_buf
.set_pos(bytes
);
801 case TTCN_EncDec::CT_JSON
: {
802 TTCN_EncDec_ErrorContext
ec("While JSON-decoding type '%s': ", p_td
.name
);
804 TTCN_EncDec_ErrorContext::error_internal
805 ("No JSON descriptor available for type '%s'.", p_td
.name
);
806 JSON_Tokenizer
tok((const char*)p_buf
.get_data(), p_buf
.get_len());
807 if(JSON_decode(p_td
, tok
, false)<0)
808 ec
.error(TTCN_EncDec::ET_INCOMPL_MSG
,
809 "Can not decode type '%s', because invalid or incomplete"
810 " message was received"
812 p_buf
.set_pos(tok
.get_buf_pos());
815 TTCN_error("Unknown coding method requested to decode type '%s'",
821 ASN_BER_TLV_t
*INTEGER::BER_encode_TLV(const TTCN_Typedescriptor_t
& p_td
,
822 unsigned p_coding
) const
825 ASN_BER_TLV_t
*new_tlv
= BER_encode_chk_bound(is_bound());
828 new_tlv
= BER_encode_TLV_INTEGER(p_coding
, val
.native
);
831 int_val_t
*tmp
= new int_val_t(BN_dup(val
.openssl
));
832 new_tlv
= BER_encode_TLV_INTEGER(p_coding
, *tmp
);
836 new_tlv
= ASN_BER_V2TLV(new_tlv
, p_td
, p_coding
);
840 boolean
INTEGER::BER_decode_TLV(const TTCN_Typedescriptor_t
& p_td
,
841 const ASN_BER_TLV_t
& p_tlv
,
847 ASN_BER_TLV_t stripped_tlv
;
848 BER_decode_strip_tags(*p_td
.ber
, p_tlv
, L_form
, stripped_tlv
);
849 TTCN_EncDec_ErrorContext
ec("While decoding INTEGER type: ");
851 boolean ret_val
= BER_decode_TLV_INTEGER(stripped_tlv
, L_form
, tmp
);
852 if (tmp
.is_native()) {
854 val
.native
= tmp
.get_val();
857 val
.openssl
= BN_dup(tmp
.get_val_openssl());
859 if (ret_val
) bound_flag
= TRUE
;
863 int INTEGER::TEXT_decode(const TTCN_Typedescriptor_t
& p_td
,
864 TTCN_Buffer
& buff
, Limit_Token_List
& limit
, boolean no_err
, boolean
/*first_call*/)
866 int decoded_length
= 0;
868 if (p_td
.text
->begin_decode
) {
870 if ((tl
= p_td
.text
->begin_decode
->match_begin(buff
)) < 0) {
871 if (no_err
) return -1;
872 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_TOKEN_ERR
,
873 "The specified token '%s' not found for '%s': ",
874 (const char*)*(p_td
.text
->begin_decode
), p_td
.name
);
877 decoded_length
+= tl
;
878 buff
.increase_pos(tl
);
880 if (buff
.get_read_len() <= 1 && no_err
) return -TTCN_EncDec::ET_LEN_ERR
;
881 if (p_td
.text
->select_token
) {
883 if ((tl
= p_td
.text
->select_token
->match_begin(buff
)) < 0) {
884 if (no_err
) return -1;
888 } else if ( p_td
.text
->val
.parameters
889 && p_td
.text
->val
.parameters
->decoding_params
.min_length
!= -1) {
890 str_len
= p_td
.text
->val
.parameters
->decoding_params
.min_length
;
891 } else if (p_td
.text
->end_decode
) {
893 if ((tl
= p_td
.text
->end_decode
->match_first(buff
)) < 0) {
894 if (no_err
) return -1;
898 } else if (limit
.has_token()) {
900 if ((tl
= limit
.match(buff
)) < 0) {
901 if (no_err
) return -1;
907 if ((tl
= integer_value_match
.match_begin(buff
)) < 0) {
908 if (no_err
) return -1;
916 char *atm
= (char*)Malloc(str_len
+ 1); // sizeof(char) == 1 by definition
917 const char *b
= (const char*)buff
.get_read_data();
918 memcpy(atm
, b
, str_len
);
923 int neg
= *atm
== 0x2d ? 1 : 0;
925 for (offs
= neg
; *(atm
+ offs
) == 0x30; offs
++) ; // E.g. 0, -0, 00001234, -00001234.
926 if (neg
&& offs
> 1) *(atm
+ offs
- 1) = *atm
; // E.g. -00001234 -> -000-1234.
929 for(; atm
[offs
] == 0x20; offs
++) ;
932 if (0 == strlen(atm
+ offs
) || 0 == from_string(atm
+offs
)) {
938 buff
.increase_pos(str_len
);
939 decoded_length
+= str_len
;
944 if (no_err
) return -1;
945 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_TOKEN_ERR
,
946 "Can not decode a valid integer for '%s': ", p_td
.name
);
948 if (p_td
.text
->end_decode
) {
950 if ((tl
= p_td
.text
->end_decode
->match_begin(buff
)) < 0) {
951 if (no_err
) return -1;
952 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_TOKEN_ERR
,
953 "The specified token '%s' not found for '%s': ",
954 (const char*)*(p_td
.text
->end_decode
), p_td
.name
);
957 decoded_length
+= tl
;
958 buff
.increase_pos(tl
);
961 return decoded_length
;
964 int INTEGER::TEXT_encode(const TTCN_Typedescriptor_t
& p_td
,
965 TTCN_Buffer
& buff
) const
967 int encoded_length
= 0;
968 if (p_td
.text
->begin_encode
) {
969 buff
.put_cs(*p_td
.text
->begin_encode
);
970 encoded_length
+= p_td
.text
->begin_encode
->lengthof();
973 TTCN_EncDec_ErrorContext::error
974 (TTCN_EncDec::ET_UNBOUND
,"Encoding an unbound value.");
975 if (p_td
.text
->end_encode
) {
976 buff
.put_cs(*p_td
.text
->end_encode
);
977 encoded_length
+=p_td
.text
->end_encode
->lengthof();
979 return encoded_length
;
983 if (native_flag
) tmp_str
= mprintf("%d", val
.native
);
984 else tmp_str
= BN_bn2dec(val
.openssl
);
985 CHARSTRING
ch(tmp_str
);
986 if (native_flag
) Free(tmp_str
);
987 else OPENSSL_free(tmp_str
);
988 if (p_td
.text
->val
.parameters
== NULL
) {
990 encoded_length
+= ch
.lengthof();
992 TTCN_TEXTdescriptor_values params
= p_td
.text
->val
.parameters
994 if (params
.min_length
< 0) {
996 encoded_length
+= ch
.lengthof();
998 unsigned char *p
= NULL
;
1000 size_t len
= params
.min_length
+ 1;
1001 buff
.get_end(p
, len
);
1002 if (params
.leading_zero
) {
1004 a
= snprintf((char*)p
, len
, "%0*d", params
.min_length
, val
.native
);
1006 int chlen
= ch
.lengthof(), pad
= 0;
1007 int neg
= native_flag
? (val
.native
< 0) : BN_is_negative(val
.openssl
);
1008 if (params
.min_length
> chlen
)
1009 pad
= params
.min_length
- chlen
+ neg
;
1012 memset(p
+ neg
, 0x30, pad
);
1013 for (int i
= 0; i
< chlen
- neg
; i
++)
1014 p
[i
+ pad
] = ch
[i
+ neg
].get_char();
1015 a
+= pad
+ chlen
- neg
;
1018 a
= snprintf((char*)p
, len
, "%*s", p_td
.text
->val
.parameters
->
1019 coding_params
.min_length
, (const char*)ch
);
1021 buff
.increase_length(a
);
1022 encoded_length
+= a
;
1025 if (p_td
.text
->end_encode
) {
1026 buff
.put_cs(*p_td
.text
->end_encode
);
1027 encoded_length
+= p_td
.text
->end_encode
->lengthof();
1029 return encoded_length
;
1032 int INTEGER::RAW_encode(const TTCN_Typedescriptor_t
& p_td
, RAW_enc_tree
& myleaf
) const
1034 if (!native_flag
) return RAW_encode_openssl(p_td
, myleaf
);
1036 int length
= (p_td
.raw
->fieldlength
+ 7) / 8; // in bytes
1037 int value
= val
.native
;
1038 boolean neg_sgbit
= (value
< 0) && (p_td
.raw
->comp
== SG_SG_BIT
);
1040 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND
,
1041 "Encoding an unbound value.");
1045 if (value
!= 0 && value
== -value
) {
1046 // value == -INT_MAX-1 a.k.a. INT_MIN a.k.a. 0x8000....
1047 INTEGER
big_value(to_openssl(val
.native
)); // too big for native
1048 return big_value
.RAW_encode_openssl(p_td
, myleaf
);
1050 if (min_bits(value
) > p_td
.raw
->fieldlength
) {
1051 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_LEN_ERR
,
1052 "There are insufficient bits to encode '%s' : ", p_td
.name
);
1053 value
= 0; // substitute with zero
1055 if ((value
< 0) && (p_td
.raw
->comp
== SG_NO
)) {
1056 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_SIGN_ERR
,
1057 "Unsigned encoding of a negative number: %s", p_td
.name
);
1060 if (neg_sgbit
) value
= -value
;
1061 //myleaf.ext_bit=EXT_BIT_NO;
1062 if (myleaf
.must_free
) Free(myleaf
.body
.leaf
.data_ptr
);
1063 if (length
> RAW_INT_ENC_LENGTH
) { // does not fit in the small buffer
1064 myleaf
.body
.leaf
.data_ptr
= bc
= (unsigned char*)Malloc(length
* sizeof(*bc
));
1065 myleaf
.must_free
= TRUE
;
1066 myleaf
.data_ptr_used
= TRUE
;
1068 else bc
= myleaf
.body
.leaf
.data_array
;
1069 for (int a
= 0; a
< length
; a
++) {
1070 bc
[a
] = value
& 0xFF;
1074 unsigned char mask
= 0x01 << (p_td
.raw
->fieldlength
- 1) % 8;
1075 bc
[length
- 1] |= mask
;
1077 return myleaf
.length
= p_td
.raw
->fieldlength
;
1080 int INTEGER::RAW_encode_openssl(const TTCN_Typedescriptor_t
& p_td
,
1081 RAW_enc_tree
& myleaf
) const
1083 unsigned char *bc
= NULL
;
1084 int length
= (p_td
.raw
->fieldlength
+ 7) / 8;
1085 BIGNUM
*D
= BN_new();
1086 BN_copy(D
, val
.openssl
);
1087 boolean neg_sgbit
= (D
->neg
) && (p_td
.raw
->comp
== SG_SG_BIT
);
1089 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND
,
1090 "Encoding an unbound value.");
1094 if (min_bits(D
) > p_td
.raw
->fieldlength
) {
1095 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_LEN_ERR
,
1096 "There are insufficient bits to encode '%s': ", p_td
.name
);
1097 // `tmp = -((-tmp) & BitMaskTable[min_bits(tmp)]);' doesn't make any sense
1098 // at all for negative values. Just simply clear the value.
1102 if ((D
->neg
) && (p_td
.raw
->comp
== SG_NO
)) {
1103 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_SIGN_ERR
,
1104 "Unsigned encoding of a negative number: %s", p_td
.name
);
1105 BN_set_negative(D
, 0);
1108 // `if (neg_sgbit) tmp->neg = tmp->neg == 0;' is not needed, because the
1109 // sign is stored separately from the number. Default encoding of negative
1110 // values in 2's complement form.
1111 if (myleaf
.must_free
) Free(myleaf
.body
.leaf
.data_ptr
);
1112 if (length
> RAW_INT_ENC_LENGTH
) {
1113 myleaf
.body
.leaf
.data_ptr
= bc
=
1114 (unsigned char *)Malloc(length
* sizeof(*bc
));
1115 myleaf
.must_free
= TRUE
;
1116 myleaf
.data_ptr_used
= TRUE
;
1118 bc
= myleaf
.body
.leaf
.data_array
;
1120 boolean twos_compl
= (D
->neg
) && !neg_sgbit
;
1121 // Conversion to 2's complement.
1123 BN_set_negative(D
, 0);
1124 for (int a
= 0; a
< D
->dmax
; a
++) D
->d
[a
] = ~D
->d
[a
];
1127 int num_bytes
= BN_num_bytes(D
);
1128 for (int a
= 0; a
< length
; a
++) {
1129 if (twos_compl
&& num_bytes
- 1 < a
) bc
[a
] = 0xff;
1130 else bc
[a
] = (D
->top
? D
->d
[0] : 0) & 0xff;
1134 unsigned char mask
= 0x01 << (p_td
.raw
->fieldlength
- 1) % 8;
1135 bc
[length
- 1] |= mask
;
1138 return myleaf
.length
= p_td
.raw
->fieldlength
;
1141 int INTEGER::RAW_decode(const TTCN_Typedescriptor_t
& p_td
, TTCN_Buffer
& buff
,
1142 int limit
, raw_order_t top_bit_ord
, boolean no_err
, int /*sel_field*/,
1143 boolean
/*first_call*/)
1146 int prepaddlength
= buff
.increase_pos_padd(p_td
.raw
->prepadding
);
1147 limit
-= prepaddlength
;
1148 int decode_length
= p_td
.raw
->fieldlength
;
1149 if (decode_length
> limit
) {
1150 if (no_err
) return -TTCN_EncDec::ET_LEN_ERR
;
1151 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_LEN_ERR
,
1152 "There are not enough bits in the buffer to decode type %s (needed: %d, "
1153 "found: %d).", p_td
.name
, decode_length
, limit
);
1154 decode_length
= limit
;
1156 int nof_unread_bits
= buff
.unread_len_bit();
1157 if (decode_length
> nof_unread_bits
) {
1158 if (no_err
) return -TTCN_EncDec::ET_INCOMPL_MSG
;
1159 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_INCOMPL_MSG
,
1160 "There are not enough bits in the buffer to decode type %s (needed: %d, "
1161 "found: %d).", p_td
.name
, decode_length
, nof_unread_bits
);
1162 decode_length
= nof_unread_bits
;
1165 if (decode_length
< 0) return -1;
1166 else if (decode_length
== 0) {
1173 unsigned char *data
= (unsigned char *) Malloc((decode_length
+ 7) / 8);
1175 boolean orders
= FALSE
;
1176 if (p_td
.raw
->bitorderinoctet
== ORDER_MSB
) orders
= TRUE
;
1177 if (p_td
.raw
->bitorderinfield
== ORDER_MSB
) orders
= !orders
;
1178 cp
.bitorder
= orders
? ORDER_MSB
: ORDER_LSB
;
1180 if (p_td
.raw
->byteorder
== ORDER_MSB
) orders
= TRUE
;
1181 if (p_td
.raw
->bitorderinfield
== ORDER_MSB
) orders
= !orders
;
1182 cp
.byteorder
= orders
? ORDER_MSB
: ORDER_LSB
;
1183 cp
.fieldorder
= p_td
.raw
->fieldorder
;
1184 cp
.hexorder
= ORDER_LSB
;
1185 buff
.get_b((size_t) decode_length
, data
, cp
, top_bit_ord
);
1186 int end_pos
= decode_length
;
1187 int idx
= (end_pos
- 1) / 8;
1188 boolean negativ_num
= FALSE
;
1189 switch (p_td
.raw
->comp
) {
1191 if (data
[idx
] >> ((end_pos
- 1) % 8) & 0x01) {
1199 negativ_num
= (data
[idx
] >> ((end_pos
- 1) % 8)) & 0x01;
1207 tmp
|= data
[0] & BitMaskTable
[end_pos
];
1210 idx
= (end_pos
- 1) / 8;
1211 tmp
<<= (end_pos
- 1) % 8 + 1;
1212 tmp
|= data
[idx
--] & BitMaskTable
[(end_pos
- 1) % 8 + 1];
1213 if (decode_length
> (RInt
) sizeof(RInt
) * 8 - 1) {
1214 BIGNUM
*D
= BN_new();
1215 BN_set_word(D
, tmp
);
1216 int pad
= tmp
== 0 ? 1 : 0;
1217 for (; idx
>= 0; idx
--) {
1218 if (pad
&& data
[idx
] != 0) {
1219 BN_set_word(D
, data
[idx
] & 0xff);
1225 BN_add_word(D
, data
[idx
] & 0xff);
1228 BIGNUM
*D_tmp
= BN_new();
1229 BN_set_bit(D_tmp
, BN_num_bits(D
));
1230 BN_sub(D
, D
, D_tmp
);
1233 else if (negativ_num
) {
1234 BN_set_negative(D
, 1);
1236 // Back to native. "BN_num_bits(D) + BN_is_negative(D) >
1237 // (RInt)sizeof(RInt) * 8 - !BN_is_negative(D)" was an over-complicated
1239 if (BN_num_bits(D
) > (RInt
) sizeof(RInt
) * 8 - 1) {
1240 native_flag
= FALSE
;
1245 val
.native
= BN_is_negative(D
) ? -D
->d
[0] : D
->d
[0];
1252 for (; idx
>= 0; idx
--) {
1254 tmp
|= data
[idx
] & 0xff;
1260 val
.native
= negativ_num
? (RInt
) -tmp
: (RInt
) tmp
;
1262 end
: decode_length
+= buff
.increase_pos_padd(p_td
.raw
->padding
);
1264 return decode_length
+ prepaddlength
;
1267 int INTEGER::XER_encode(const XERdescriptor_t
& p_td
, TTCN_Buffer
& p_buf
,
1268 unsigned int flavor
, int indent
) const
1271 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND
,
1272 "Encoding an unbound integer value.");
1274 int encoded_length
= (int) p_buf
.get_len();
1276 flavor
|= SIMPLE_TYPE
;
1277 flavor
&= ~XER_RECOF
; // integer doesn't care
1278 if (begin_xml(p_td
, p_buf
, flavor
, indent
, false) == -1) --encoded_length
;
1282 tmp_str
= mprintf("%d", val
.native
);
1284 tmp_str
= BN_bn2dec(val
.openssl
);
1285 CHARSTRING
value(tmp_str
);
1289 OPENSSL_free(tmp_str
);
1290 p_buf
.put_string(value
);
1292 end_xml(p_td
, p_buf
, flavor
, indent
, false);
1294 return (int) p_buf
.get_len() - encoded_length
;
1297 int INTEGER::XER_decode(const XERdescriptor_t
& p_td
, XmlReaderWrap
& reader
,
1298 unsigned int flavor
)
1300 const boolean exer
= is_exer(flavor
);
1301 int depth
= -1, success
= reader
.Ok(), type
;
1302 const char * value
= 0;
1304 boolean own_tag
= !(exer
&& (p_td
.xer_bits
& UNTAGGED
)) && !is_exerlist(flavor
);
1306 if (!own_tag
) goto tagless
;
1307 if (exer
&& (p_td
.xer_bits
& XER_ATTRIBUTE
)) {
1308 verify_name(reader
, p_td
, exer
);
1310 value
= (const char *)reader
.Value();
1312 for (; *value
&& isspace(*value
); ++value
) {}
1314 if (get_nof_digits() != (int)strlen(value
) - (value
[0] == '-') ? 1 : 0) {
1317 // Let the caller do reader.AdvanceAttribute();
1320 for (; success
== 1; success
= reader
.Read()) {
1321 type
= reader
.NodeType();
1322 if (XML_READER_TYPE_ELEMENT
== type
) {
1323 verify_name(reader
, p_td
, exer
);
1324 if (reader
.IsEmptyElement()) {
1325 if (exer
&& p_td
.dfeValue
!= 0) {
1326 *this = *static_cast<const INTEGER
*> (p_td
.dfeValue
);
1331 depth
= reader
.Depth();
1333 else if (XML_READER_TYPE_TEXT
== type
&& depth
!= -1) {
1334 value
= (const char*) reader
.Value();
1335 for (; *value
&& isspace(*value
); ++value
) {}
1337 if (get_nof_digits() != (int)strlen(value
) - (value
[0] == '-') ? 1 : 0) {
1341 else if (XML_READER_TYPE_END_ELEMENT
== type
) {
1342 verify_end(reader
, p_td
, depth
, exer
);
1343 if (!bound_flag
&& exer
&& p_td
.dfeValue
!= 0) {
1344 *this = *static_cast<const INTEGER
*> (p_td
.dfeValue
);
1350 } // if not attribute
1355 int INTEGER::get_nof_digits()
1359 RInt x
= val
.native
;
1360 if (x
== 0) return 1;
1367 BIGNUM
*x
= BN_new();
1368 BN_copy(x
, val
.openssl
);
1369 if (BN_is_zero(x
)) return 1;
1371 while (!BN_is_zero(x
)) {
1379 int INTEGER::JSON_encode(const TTCN_Typedescriptor_t
&, JSON_Tokenizer
& p_tok
) const
1382 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND
,
1383 "Encoding an unbound integer value.");
1388 tmp_str
= mprintf("%d", val
.native
);
1390 tmp_str
= BN_bn2dec(val
.openssl
);
1393 int enc_len
= p_tok
.put_next_token(JSON_TOKEN_NUMBER
, tmp_str
);
1398 OPENSSL_free(tmp_str
);
1404 int INTEGER::JSON_decode(const TTCN_Typedescriptor_t
& p_td
, JSON_Tokenizer
& p_tok
, boolean p_silent
)
1406 json_token_t token
= JSON_TOKEN_NONE
;
1408 size_t value_len
= 0;
1410 boolean use_default
= p_td
.json
->default_value
&& 0 == p_tok
.get_buffer_length();
1412 // No JSON data in the buffer -> use default value
1413 value
= (char*)p_td
.json
->default_value
;
1414 value_len
= strlen(value
);
1416 dec_len
= p_tok
.get_next_token(&token
, &value
, &value_len
);
1418 if (JSON_TOKEN_ERROR
== token
) {
1419 JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG
, JSON_DEC_BAD_TOKEN_ERROR
, "");
1420 return JSON_ERROR_FATAL
;
1422 else if (JSON_TOKEN_NUMBER
== token
|| use_default
) {
1423 char* number
= mcopystrn(value
, value_len
);
1424 if (from_string(number
) && (int)value_len
== get_nof_digits() + ('-' == value
[0] ? 1 : 0)) {
1427 JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG
, JSON_DEC_FORMAT_ERROR
, "number", "integer");
1429 dec_len
= JSON_ERROR_FATAL
;
1434 return JSON_ERROR_INVALID_TOKEN
;
1440 // Global functions.
1442 INTEGER
operator+(int int_value
, const INTEGER
& other_value
)
1444 other_value
.must_bound("Unbound right operand of integer addition.");
1445 return INTEGER(int_value
) + other_value
;
1448 INTEGER
operator-(int int_value
, const INTEGER
& other_value
)
1450 other_value
.must_bound("Unbound right operand of integer subtraction.");
1451 return INTEGER(int_value
) - other_value
;
1454 INTEGER
operator*(int int_value
, const INTEGER
& other_value
)
1456 other_value
.must_bound("Unbound right operand of integer multiplication.");
1457 return INTEGER(int_value
) * other_value
;
1460 INTEGER
operator/(int int_value
, const INTEGER
& other_value
)
1462 other_value
.must_bound("Unbound right operand of integer division.");
1463 if (other_value
.get_val() == 0)
1464 TTCN_error("Integer division by zero.");
1465 return INTEGER(int_value
) / other_value
;
1468 INTEGER
rem(int left_value
, int right_value
)
1470 if (right_value
== 0)
1471 TTCN_error("The right operand of rem operator is zero.");
1472 return INTEGER(left_value
- right_value
* (left_value
/ right_value
));
1475 INTEGER
rem(const INTEGER
& left_value
, const INTEGER
& right_value
)
1477 left_value
.must_bound("Unbound left operand of rem operator.");
1478 right_value
.must_bound("Unbound right operand of rem operator.");
1479 return left_value
- right_value
* (left_value
/ right_value
);
1482 INTEGER
rem(const INTEGER
& left_value
, int right_value
)
1484 left_value
.must_bound("Unbound left operand of rem operator.");
1485 return rem(left_value
, INTEGER(right_value
));
1488 INTEGER
rem(int left_value
, const INTEGER
& right_value
)
1490 right_value
.must_bound("Unbound right operand of rem operator.");
1491 return rem(INTEGER(left_value
), right_value
);
1494 INTEGER
mod(int left_value
, int right_value
)
1496 if (right_value
< 0) right_value
= -right_value
;
1497 else if (right_value
== 0)
1498 TTCN_error("The right operand of mod operator is zero.");
1499 if (left_value
> 0) return rem(left_value
, right_value
);
1501 int result
= rem(left_value
, right_value
);
1502 if (result
== 0) return 0;
1503 else return INTEGER(right_value
+ result
);
1507 INTEGER
mod(const INTEGER
& left_value
, const INTEGER
& right_value
)
1509 left_value
.must_bound("Unbound left operand of mod operator.");
1510 right_value
.must_bound("Unbound right operand of mod operator.");
1511 INTEGER
right_value_abs(right_value
);
1512 if (right_value
< 0) right_value_abs
= -right_value_abs
;
1513 else if (right_value
== 0)
1514 TTCN_error("The right operand of mod operator is zero.");
1515 if (left_value
> 0) {
1516 return rem(left_value
, right_value_abs
);
1518 INTEGER result
= rem(left_value
, right_value_abs
);
1519 if (result
== 0) return INTEGER((int)0);
1520 else return INTEGER(right_value_abs
+ result
);
1524 INTEGER
mod(const INTEGER
& left_value
, int right_value
)
1526 left_value
.must_bound("Unbound left operand of mod operator.");
1527 return mod(left_value
, INTEGER(right_value
));
1530 INTEGER
mod(int left_value
, const INTEGER
& right_value
)
1532 right_value
.must_bound("Unbound right operand of mod operator.");
1533 return mod(INTEGER(left_value
), right_value
);
1536 boolean
operator==(int int_value
, const INTEGER
& other_value
)
1538 other_value
.must_bound("Unbound right operand of integer comparison.");
1539 return INTEGER(int_value
) == other_value
;
1542 boolean
operator<(int int_value
, const INTEGER
& other_value
)
1544 other_value
.must_bound("Unbound right operand of integer comparison.");
1545 return INTEGER(int_value
) < other_value
;
1548 boolean
operator>(int int_value
, const INTEGER
& other_value
)
1550 other_value
.must_bound("Unbound right operand of integer comparison.");
1551 return INTEGER(int_value
) > other_value
;
1554 // Integer template class.
1556 void INTEGER_template::clean_up()
1558 switch (template_selection
) {
1559 case SPECIFIC_VALUE
:
1560 if (unlikely(!int_val
.native_flag
)) BN_free(int_val
.val
.openssl
);
1563 case COMPLEMENTED_LIST
:
1564 delete [] value_list
.list_value
;
1567 if (value_range
.min_is_present
&& unlikely(!value_range
.min_value
.native_flag
))
1568 BN_free(value_range
.min_value
.val
.openssl
);
1569 if (value_range
.max_is_present
&& unlikely(!value_range
.max_value
.native_flag
))
1570 BN_free(value_range
.max_value
.val
.openssl
);
1575 template_selection
= UNINITIALIZED_TEMPLATE
;
1578 void INTEGER_template::copy_template(const INTEGER_template
& other_value
)
1580 switch (other_value
.template_selection
) {
1581 case SPECIFIC_VALUE
:
1582 int_val
.native_flag
= other_value
.int_val
.native_flag
;
1583 if (likely(int_val
.native_flag
))
1584 int_val
.val
.native
= other_value
.int_val
.val
.native
;
1585 else int_val
.val
.openssl
= BN_dup(other_value
.int_val
.val
.openssl
);
1592 case COMPLEMENTED_LIST
:
1593 value_list
.n_values
= other_value
.value_list
.n_values
;
1594 value_list
.list_value
= new INTEGER_template
[value_list
.n_values
];
1595 for (unsigned int i
= 0; i
< value_list
.n_values
; i
++)
1596 value_list
.list_value
[i
].copy_template(
1597 other_value
.value_list
.list_value
[i
]);
1600 value_range
.min_is_present
= other_value
.value_range
.min_is_present
;
1601 if (value_range
.min_is_present
) {
1602 value_range
.min_value
.native_flag
= other_value
.value_range
.min_value
.native_flag
;
1603 if (likely(value_range
.min_value
.native_flag
))
1604 value_range
.min_value
.val
.native
=
1605 other_value
.value_range
.min_value
.val
.native
;
1607 value_range
.min_value
.val
.openssl
=
1608 BN_dup(other_value
.value_range
.min_value
.val
.openssl
);
1610 value_range
.max_is_present
= other_value
.value_range
.max_is_present
;
1611 if (value_range
.max_is_present
) {
1612 value_range
.max_value
.native_flag
= other_value
.value_range
.max_value
.native_flag
;
1613 if (likely(value_range
.max_value
.native_flag
))
1614 value_range
.max_value
.val
.native
=
1615 other_value
.value_range
.max_value
.val
.native
;
1617 value_range
.max_value
.val
.openssl
=
1618 BN_dup(other_value
.value_range
.max_value
.val
.openssl
);
1622 TTCN_error("Copying an uninitialized/unsupported integer template.");
1624 set_selection(other_value
);
1627 INTEGER_template::INTEGER_template()
1631 INTEGER_template::INTEGER_template(template_sel other_value
)
1632 : Base_Template(other_value
)
1634 check_single_selection(other_value
);
1637 INTEGER_template::INTEGER_template(int other_value
)
1638 : Base_Template(SPECIFIC_VALUE
)
1640 int_val
.native_flag
= TRUE
;
1641 int_val
.val
.native
= other_value
;
1644 INTEGER_template::INTEGER_template(const INTEGER
& other_value
)
1645 : Base_Template(SPECIFIC_VALUE
)
1647 other_value
.must_bound("Creating a template from an unbound integer "
1649 int_val_t other_value_int
= other_value
.get_val();
1650 int_val
.native_flag
= other_value_int
.native_flag
;
1651 if (likely(int_val
.native_flag
))
1652 int_val
.val
.native
= other_value_int
.val
.native
;
1653 else int_val
.val
.openssl
= BN_dup(other_value_int
.val
.openssl
);
1656 INTEGER_template::INTEGER_template(const OPTIONAL
<INTEGER
>& other_value
)
1658 switch (other_value
.get_selection()) {
1659 case OPTIONAL_PRESENT
: {
1660 set_selection(SPECIFIC_VALUE
);
1661 int_val_t other_value_int
= ((const INTEGER
&)other_value
).get_val();
1662 int_val
.native_flag
= other_value_int
.native_flag
;
1663 if (likely(int_val
.native_flag
))
1664 int_val
.val
.native
= other_value_int
.val
.native
;
1665 else int_val
.val
.openssl
= BN_dup(other_value_int
.val
.openssl
);
1668 set_selection(OMIT_VALUE
);
1671 TTCN_error("Creating an integer template from an unbound optional field.");
1675 INTEGER_template::INTEGER_template(const INTEGER_template
& other_value
)
1678 copy_template(other_value
);
1681 INTEGER_template::~INTEGER_template()
1686 INTEGER_template
& INTEGER_template::operator=(template_sel other_value
)
1688 check_single_selection(other_value
);
1690 set_selection(other_value
);
1694 INTEGER_template
& INTEGER_template::operator=(int other_value
)
1697 set_selection(SPECIFIC_VALUE
);
1698 int_val
.native_flag
= TRUE
;
1699 int_val
.val
.native
= other_value
;
1703 INTEGER_template
& INTEGER_template::operator=(const INTEGER
& other_value
)
1705 other_value
.must_bound("Assignment of an unbound integer value to a "
1708 set_selection(SPECIFIC_VALUE
);
1709 int_val_t other_value_int
= other_value
.get_val();
1710 int_val
.native_flag
= other_value_int
.native_flag
;
1711 if (likely(int_val
.native_flag
))
1712 int_val
.val
.native
= other_value_int
.val
.native
;
1713 else int_val
.val
.openssl
= BN_dup(other_value_int
.val
.openssl
);
1717 INTEGER_template
& INTEGER_template::operator=
1718 (const OPTIONAL
<INTEGER
>& other_value
)
1721 switch (other_value
.get_selection()) {
1722 case OPTIONAL_PRESENT
: {
1723 set_selection(SPECIFIC_VALUE
);
1724 int_val_t other_value_int
= ((const INTEGER
&)other_value
).get_val();
1725 int_val
.native_flag
= other_value_int
.native_flag
;
1726 if (likely(int_val
.native_flag
))
1727 int_val
.val
.native
= other_value_int
.val
.native
;
1728 else int_val
.val
.openssl
= BN_dup(other_value_int
.val
.openssl
);
1731 set_selection(OMIT_VALUE
);
1734 TTCN_error("Assignment of an unbound optional field to an integer "
1740 INTEGER_template
& INTEGER_template::operator=
1741 (const INTEGER_template
& other_value
)
1743 if (&other_value
!= this) {
1745 copy_template(other_value
);
1750 boolean
INTEGER_template::match(int other_value
) const
1752 switch (template_selection
) {
1753 case SPECIFIC_VALUE
:
1754 if (likely(int_val
.native_flag
)) return int_val
.val
.native
== other_value
;
1755 return int_val_t(BN_dup(int_val
.val
.openssl
)) == other_value
;
1762 case COMPLEMENTED_LIST
:
1763 for(unsigned int i
= 0; i
< value_list
.n_values
; i
++)
1764 if (value_list
.list_value
[i
].match(other_value
))
1765 return template_selection
== VALUE_LIST
;
1766 return template_selection
== COMPLEMENTED_LIST
;
1768 boolean lower_boundary
= !value_range
.min_is_present
;
1769 boolean upper_boundary
= !value_range
.max_is_present
;
1770 // Lower boundary is set.
1771 if (!lower_boundary
) {
1772 lower_boundary
= (likely(value_range
.min_value
.native_flag
) ?
1773 int_val_t(value_range
.min_value
.val
.native
) :
1774 int_val_t(BN_dup(value_range
.min_value
.val
.openssl
))) <= other_value
;
1776 // Upper boundary is set.
1777 if (!upper_boundary
) {
1778 upper_boundary
= (likely(value_range
.max_value
.native_flag
) ?
1779 int_val_t(value_range
.max_value
.val
.native
) :
1780 int_val_t(BN_dup(value_range
.max_value
.val
.openssl
))) >= other_value
;
1782 return lower_boundary
&& upper_boundary
; }
1784 TTCN_error("Matching with an uninitialized/unsupported integer "
1790 boolean
INTEGER_template::match(const INTEGER
& other_value
) const
1792 if (!other_value
.is_bound()) return FALSE
;
1793 switch (template_selection
) {
1794 case SPECIFIC_VALUE
: {
1795 int_val_t int_val_int
= likely(int_val
.native_flag
) ?
1796 int_val_t(int_val
.val
.native
) : int_val_t(BN_dup(int_val
.val
.openssl
));
1797 return int_val_int
== other_value
.get_val(); }
1804 case COMPLEMENTED_LIST
: // Merged cases.
1805 for (unsigned int i
= 0; i
< value_list
.n_values
; i
++)
1806 if (value_list
.list_value
[i
].match(other_value
))
1807 return template_selection
== VALUE_LIST
;
1808 return template_selection
== COMPLEMENTED_LIST
;
1810 boolean lower_boundary
= !value_range
.min_is_present
;
1811 boolean upper_boundary
= !value_range
.max_is_present
;
1812 // Lower boundary is set.
1813 if (!lower_boundary
) {
1814 lower_boundary
= (likely(value_range
.min_value
.native_flag
) ?
1815 int_val_t(value_range
.min_value
.val
.native
) :
1816 int_val_t(BN_dup(value_range
.min_value
.val
.openssl
))) <= other_value
.get_val();
1818 // Upper boundary is set.
1819 if (!upper_boundary
) {
1820 upper_boundary
= (likely(value_range
.max_value
.native_flag
) ?
1821 int_val_t(value_range
.max_value
.val
.native
) :
1822 int_val_t(BN_dup(value_range
.max_value
.val
.openssl
))) >= other_value
.get_val();
1824 return lower_boundary
&& upper_boundary
; }
1826 TTCN_error("Matching with an uninitialized/unsupported integer "
1832 INTEGER
INTEGER_template::valueof() const
1834 if (template_selection
!= SPECIFIC_VALUE
|| is_ifpresent
)
1835 TTCN_error("Performing a valueof or send operation on a non-specific "
1836 "integer template.");
1837 if (likely(int_val
.native_flag
)) return INTEGER(int_val
.val
.native
);
1838 else return INTEGER(BN_dup(int_val
.val
.openssl
));
1841 void INTEGER_template::set_type(template_sel template_type
,
1842 unsigned int list_length
)
1845 switch (template_type
) {
1847 case COMPLEMENTED_LIST
:
1848 set_selection(template_type
);
1849 value_list
.n_values
= list_length
;
1850 value_list
.list_value
= new INTEGER_template
[list_length
];
1853 set_selection(VALUE_RANGE
);
1854 value_range
.min_is_present
= FALSE
;
1855 value_range
.max_is_present
= FALSE
;
1858 TTCN_error("Setting an invalid type for an integer template.");
1862 INTEGER_template
& INTEGER_template::list_item(unsigned int list_index
)
1864 if (template_selection
!= VALUE_LIST
&&
1865 template_selection
!= COMPLEMENTED_LIST
)
1866 TTCN_error("Accessing a list element of a non-list integer template.");
1867 if (list_index
>= value_list
.n_values
)
1868 TTCN_error("Index overflow in an integer value list template.");
1869 return value_list
.list_value
[list_index
];
1872 void INTEGER_template::set_min(int min_value
)
1874 if (template_selection
!= VALUE_RANGE
)
1875 TTCN_error("Integer template is not range when setting lower limit.");
1876 if (value_range
.max_is_present
) {
1877 int_val_t max_value_int
= likely(value_range
.max_value
.native_flag
) ?
1878 int_val_t(value_range
.max_value
.val
.native
) :
1879 int_val_t(BN_dup(value_range
.max_value
.val
.openssl
));
1880 if (max_value_int
< min_value
)
1881 TTCN_error("The lower limit of the range is greater than the upper "
1882 "limit in an integer template.");
1884 value_range
.min_is_present
= TRUE
;
1885 value_range
.min_value
.native_flag
= TRUE
;
1886 value_range
.min_value
.val
.native
= min_value
;
1889 void INTEGER_template::set_min(const INTEGER
& min_value
)
1891 // Redundant, but performace matters. :)
1892 min_value
.must_bound("Using an unbound value when setting the lower bound "
1893 "in an integer range template.");
1894 if (template_selection
!= VALUE_RANGE
)
1895 TTCN_error("Integer template is not range when setting lower limit.");
1896 int_val_t min_value_int
= min_value
.get_val();
1897 if (value_range
.max_is_present
) {
1898 int_val_t max_value_int
= likely(value_range
.max_value
.native_flag
) ?
1899 int_val_t(value_range
.max_value
.val
.native
) :
1900 int_val_t(BN_dup(value_range
.max_value
.val
.openssl
));
1901 if (max_value_int
< min_value_int
)
1902 TTCN_error("The lower limit of the range is greater than the upper "
1903 "limit in an integer template.");
1905 value_range
.min_is_present
= TRUE
;
1906 value_range
.min_value
.native_flag
= min_value_int
.native_flag
;
1907 if (likely(value_range
.min_value
.native_flag
))
1908 value_range
.min_value
.val
.native
= min_value_int
.val
.native
;
1909 else value_range
.min_value
.val
.openssl
= BN_dup(min_value_int
.val
.openssl
);
1912 void INTEGER_template::set_max(int max_value
)
1914 if (template_selection
!= VALUE_RANGE
)
1915 TTCN_error("Integer template is not range when setting upper limit.");
1916 if (value_range
.min_is_present
) {
1917 int_val_t min_value_int
= likely(value_range
.min_value
.native_flag
) ?
1918 int_val_t(value_range
.min_value
.val
.native
) :
1919 int_val_t(BN_dup(value_range
.min_value
.val
.openssl
));
1920 if (min_value_int
> max_value
)
1921 TTCN_error("The upper limit of the range is smaller than the lower "
1922 "limit in an integer template.");
1924 value_range
.max_is_present
= TRUE
;
1925 value_range
.max_value
.native_flag
= TRUE
;
1926 value_range
.max_value
.val
.native
= max_value
;
1929 void INTEGER_template::set_max(const INTEGER
& max_value
)
1931 max_value
.must_bound("Using an unbound value when setting the upper bound "
1932 "in an integer range template.");
1933 if (template_selection
!= VALUE_RANGE
)
1934 TTCN_error("Integer template is not range when setting upper limit.");
1935 int_val_t max_value_int
= max_value
.get_val();
1936 if (value_range
.min_is_present
) {
1937 int_val_t min_value_int
= likely(value_range
.min_value
.native_flag
) ?
1938 int_val_t(value_range
.min_value
.val
.native
) :
1939 int_val_t(BN_dup(value_range
.min_value
.val
.openssl
));
1940 if (min_value_int
> max_value_int
)
1941 TTCN_error("The upper limit of the range is smaller than the lower "
1942 "limit in an integer template.");
1944 value_range
.max_is_present
= TRUE
;
1945 value_range
.max_value
.native_flag
= max_value_int
.native_flag
;
1946 if (likely(value_range
.max_value
.native_flag
))
1947 value_range
.max_value
.val
.native
= max_value_int
.val
.native
;
1948 else value_range
.max_value
.val
.openssl
= BN_dup(max_value_int
.val
.openssl
);
1951 void INTEGER_template::log() const
1953 switch (template_selection
) {
1954 case SPECIFIC_VALUE
: {
1955 int_val_t int_val_int
= likely(int_val
.native_flag
) ?
1956 int_val_t(int_val
.val
.native
) : int_val_t(BN_dup(int_val
.val
.openssl
));
1957 char *tmp_str
= int_val_int
.as_string();
1958 TTCN_Logger::log_event("%s", tmp_str
);
1961 case COMPLEMENTED_LIST
:
1962 TTCN_Logger::log_event_str("complement ");
1965 TTCN_Logger::log_char('(');
1966 for (unsigned int i
= 0; i
< value_list
.n_values
; i
++) {
1967 if (i
> 0) TTCN_Logger::log_event_str(", ");
1968 value_list
.list_value
[i
].log();
1970 TTCN_Logger::log_char(')');
1973 TTCN_Logger::log_char('(');
1974 if (value_range
.min_is_present
) {
1975 int_val_t min_value_int
= likely(value_range
.min_value
.native_flag
) ?
1976 int_val_t(value_range
.min_value
.val
.native
) :
1977 int_val_t(BN_dup(value_range
.min_value
.val
.openssl
));
1978 char *min_str
= min_value_int
.as_string();
1979 TTCN_Logger::log_event("%s", min_str
);
1982 TTCN_Logger::log_event_str("-infinity");
1984 TTCN_Logger::log_event_str(" .. ");
1985 if (value_range
.max_is_present
) {
1986 int_val_t max_value_int
= likely(value_range
.max_value
.native_flag
) ?
1987 int_val_t(value_range
.max_value
.val
.native
) :
1988 int_val_t(BN_dup(value_range
.max_value
.val
.openssl
));
1989 char *max_str
= max_value_int
.as_string();
1990 TTCN_Logger::log_event("%s", max_str
);
1993 TTCN_Logger::log_event_str("infinity");
1995 TTCN_Logger::log_char(')');
2004 void INTEGER_template::log_match(const INTEGER
& match_value
) const
2006 if (TTCN_Logger::VERBOSITY_COMPACT
== TTCN_Logger::get_matching_verbosity()
2007 && TTCN_Logger::get_logmatch_buffer_len() != 0) {
2008 TTCN_Logger::print_logmatch_buffer();
2009 TTCN_Logger::log_event_str(" := ");
2012 TTCN_Logger::log_event_str(" with ");
2014 if (match(match_value
)) TTCN_Logger::log_event_str(" matched");
2015 else TTCN_Logger::log_event_str(" unmatched");
2018 void INTEGER_template::set_param(Module_Param
& param
) {
2019 param
.basic_check(Module_Param::BC_TEMPLATE
, "integer template");
2020 switch (param
.get_type()) {
2021 case Module_Param::MP_Omit
:
2024 case Module_Param::MP_Any
:
2027 case Module_Param::MP_AnyOrNone
:
2028 *this = ANY_OR_OMIT
;
2030 case Module_Param::MP_List_Template
:
2031 case Module_Param::MP_ComplementList_Template
:
2032 set_type(param
.get_type()==Module_Param::MP_List_Template
? VALUE_LIST
: COMPLEMENTED_LIST
, param
.get_size());
2033 for (size_t i
=0; i
<param
.get_size(); i
++) {
2034 list_item(i
).set_param(*param
.get_elem(i
));
2037 case Module_Param::MP_Integer
: {
2039 tmp
.set_val(*param
.get_integer());
2042 case Module_Param::MP_IntRange
: {
2043 set_type(VALUE_RANGE
);
2044 if (param
.get_lower_int()!=NULL
) {
2046 tmp
.set_val(*param
.get_lower_int());
2049 if (param
.get_upper_int()!=NULL
) {
2051 tmp
.set_val(*param
.get_upper_int());
2056 param
.type_error("integer template");
2058 is_ifpresent
= param
.get_ifpresent();
2061 void INTEGER_template::encode_text(Text_Buf
& text_buf
) const
2063 encode_text_base(text_buf
);
2064 switch (template_selection
) {
2069 case SPECIFIC_VALUE
:
2070 text_buf
.push_int(likely(int_val
.native_flag
) ? int_val_t(int_val
.val
.native
)
2071 : int_val_t(BN_dup(int_val
.val
.openssl
)));
2074 case COMPLEMENTED_LIST
:
2075 text_buf
.push_int(value_list
.n_values
);
2076 for (unsigned int i
= 0; i
< value_list
.n_values
; i
++)
2077 value_list
.list_value
[i
].encode_text(text_buf
);
2080 text_buf
.push_int(value_range
.min_is_present
? 1 : 0);
2081 if (value_range
.min_is_present
)
2082 text_buf
.push_int(likely(value_range
.min_value
.native_flag
) ?
2083 int_val_t(value_range
.min_value
.val
.native
) :
2084 int_val_t(BN_dup(value_range
.min_value
.val
.openssl
)));
2085 text_buf
.push_int(value_range
.max_is_present
? 1 : 0);
2086 if (value_range
.max_is_present
)
2087 text_buf
.push_int(likely(value_range
.max_value
.native_flag
) ?
2088 int_val_t(value_range
.max_value
.val
.native
) :
2089 int_val_t(BN_dup(value_range
.max_value
.val
.openssl
)));
2092 TTCN_error("Text encoder: Encoding an uninitialized/unsupported integer "
2097 void INTEGER_template::decode_text(Text_Buf
& text_buf
)
2100 decode_text_base(text_buf
);
2101 switch (template_selection
) {
2106 case SPECIFIC_VALUE
: {
2107 int_val_t int_val_int
= text_buf
.pull_int();
2108 int_val
.native_flag
= int_val_int
.native_flag
;
2109 if (likely(int_val
.native_flag
)) int_val
.val
.native
= int_val_int
.val
.native
;
2110 else int_val
.val
.openssl
= BN_dup(int_val_int
.val
.openssl
);
2113 case COMPLEMENTED_LIST
:
2114 value_list
.n_values
= text_buf
.pull_int().get_val();
2115 value_list
.list_value
= new INTEGER_template
[value_list
.n_values
];
2116 for (unsigned int i
= 0; i
< value_list
.n_values
; i
++)
2117 value_list
.list_value
[i
].decode_text(text_buf
);
2120 value_range
.min_is_present
= text_buf
.pull_int() != 0;
2121 if (value_range
.min_is_present
) {
2122 int_val_t min_value_int
= text_buf
.pull_int();
2123 value_range
.min_value
.native_flag
= min_value_int
.native_flag
;
2124 if (likely(value_range
.min_value
.native_flag
))
2125 value_range
.min_value
.val
.native
= min_value_int
.val
.native
;
2126 else value_range
.min_value
.val
.openssl
= BN_dup(min_value_int
.val
.openssl
);
2128 value_range
.max_is_present
= text_buf
.pull_int() != 0;
2129 if (value_range
.max_is_present
) {
2130 int_val_t max_value_int
= text_buf
.pull_int();
2131 value_range
.max_value
.native_flag
= max_value_int
.native_flag
;
2132 if (likely(value_range
.max_value
.native_flag
))
2133 value_range
.max_value
.val
.native
= max_value_int
.val
.native
;
2134 else value_range
.max_value
.val
.openssl
= BN_dup(max_value_int
.val
.openssl
);
2138 TTCN_error("Text decoder: An unknown/unsupported selection was received "
2139 "for an integer template.");
2143 boolean
INTEGER_template::is_present() const
2145 if (template_selection
==UNINITIALIZED_TEMPLATE
) return FALSE
;
2146 return !match_omit();
2149 boolean
INTEGER_template::match_omit() const
2151 if (is_ifpresent
) return TRUE
;
2152 switch (template_selection
) {
2157 case COMPLEMENTED_LIST
:
2158 for (unsigned int i
=0; i
<value_list
.n_values
; i
++)
2159 if (value_list
.list_value
[i
].match_omit())
2160 return template_selection
==VALUE_LIST
;
2161 return template_selection
==COMPLEMENTED_LIST
;
2168 #ifndef TITAN_RUNTIME_2
2169 void INTEGER_template::check_restriction(template_res t_res
, const char* t_name
) const
2171 if (template_selection
==UNINITIALIZED_TEMPLATE
) return;
2172 switch ((t_name
&&(t_res
==TR_VALUE
))?TR_OMIT
:t_res
) {
2174 if (!is_ifpresent
&& template_selection
==SPECIFIC_VALUE
) return;
2177 if (!is_ifpresent
&& (template_selection
==OMIT_VALUE
||
2178 template_selection
==SPECIFIC_VALUE
)) return;
2181 if (!match_omit()) return;
2186 TTCN_error("Restriction `%s' on template of type %s violated.",
2187 get_res_name(t_res
), t_name
? t_name
: "integer");