1 ///////////////////////////////////////////////////////////////////////////////
2 // Copyright (c) 2000-2015 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 Module_Param_Ptr mp
= ¶m
;
645 if (param
.get_type() == Module_Param::MP_Reference
) {
646 mp
= param
.get_referenced_param();
648 switch (mp
->get_type()) {
649 case Module_Param::MP_Integer
: {
652 const int_val_t
* const int_val
= mp
->get_integer();
653 native_flag
= int_val
->is_native();
654 if (likely(native_flag
)){
655 val
.native
= int_val
->get_val();
657 val
.openssl
= BN_dup(int_val
->get_val_openssl());
660 case Module_Param::MP_Expression
:
661 switch (mp
->get_expr_type()) {
662 case Module_Param::EXPR_NEGATE
: {
664 operand
.set_param(*mp
->get_operand1());
667 case Module_Param::EXPR_ADD
: {
668 INTEGER operand1
, operand2
;
669 operand1
.set_param(*mp
->get_operand1());
670 operand2
.set_param(*mp
->get_operand2());
671 *this = operand1
+ operand2
;
673 case Module_Param::EXPR_SUBTRACT
: {
674 INTEGER operand1
, operand2
;
675 operand1
.set_param(*mp
->get_operand1());
676 operand2
.set_param(*mp
->get_operand2());
677 *this = operand1
- operand2
;
679 case Module_Param::EXPR_MULTIPLY
: {
680 INTEGER operand1
, operand2
;
681 operand1
.set_param(*mp
->get_operand1());
682 operand2
.set_param(*mp
->get_operand2());
683 *this = operand1
* operand2
;
685 case Module_Param::EXPR_DIVIDE
: {
686 INTEGER operand1
, operand2
;
687 operand1
.set_param(*mp
->get_operand1());
688 operand2
.set_param(*mp
->get_operand2());
690 param
.error("Integer division by zero.");
692 *this = operand1
/ operand2
;
695 param
.expr_type_error("an integer");
700 param
.type_error("integer value");
705 Module_Param
* INTEGER::get_param(Module_Param_Name
& /* param_name */) const
708 return new Module_Param_Unbound();
711 return new Module_Param_Integer(new int_val_t(val
.native
));
713 return new Module_Param_Integer(new int_val_t(BN_dup(val
.openssl
)));
716 void INTEGER::encode_text(Text_Buf
& text_buf
) const
718 must_bound("Text encoder: Encoding an unbound integer value.");
719 if (likely(native_flag
)) {
720 text_buf
.push_int(val
.native
);
722 int_val_t
*tmp
= new int_val_t(BN_dup(val
.openssl
));
723 text_buf
.push_int(*tmp
);
728 void INTEGER::decode_text(Text_Buf
& text_buf
)
732 int_val_t
tmp(text_buf
.pull_int());
733 if (likely(tmp
.native_flag
)) {
735 val
.native
= tmp
.get_val();
738 val
.openssl
= BN_dup(tmp
.get_val_openssl());
742 void INTEGER::encode(const TTCN_Typedescriptor_t
& p_td
, TTCN_Buffer
& p_buf
,
743 TTCN_EncDec::coding_t p_coding
, ...) const
746 va_start(pvar
, p_coding
);
748 case TTCN_EncDec::CT_BER
: {
749 TTCN_EncDec_ErrorContext
ec("While BER-encoding type '%s': ", p_td
.name
);
750 unsigned BER_coding
=va_arg(pvar
, unsigned);
751 BER_encode_chk_coding(BER_coding
);
752 ASN_BER_TLV_t
*tlv
=BER_encode_TLV(p_td
, BER_coding
);
753 tlv
->put_in_buffer(p_buf
);
754 ASN_BER_TLV_t::destruct(tlv
);
756 case TTCN_EncDec::CT_RAW
: {
757 TTCN_EncDec_ErrorContext
ec("While RAW-encoding type '%s': ", p_td
.name
);
759 TTCN_EncDec_ErrorContext::error_internal
760 ("No RAW descriptor available for type '%s'.", p_td
.name
);
764 RAW_enc_tree
root(TRUE
,NULL
,&rp
,1,p_td
.raw
);
765 RAW_encode(p_td
, root
);
766 root
.put_to_buf(p_buf
);
768 case TTCN_EncDec::CT_TEXT
: {
769 TTCN_EncDec_ErrorContext
ec("While TEXT-encoding type '%s': ", p_td
.name
);
771 TTCN_EncDec_ErrorContext::error_internal
772 ("No TEXT descriptor available for type '%s'.", p_td
.name
);
773 TEXT_encode(p_td
,p_buf
);
775 case TTCN_EncDec::CT_XER
: {
776 TTCN_EncDec_ErrorContext
ec("While XER-encoding type '%s': ", p_td
.name
);
777 unsigned XER_coding
=va_arg(pvar
, unsigned);
778 XER_encode(*p_td
.xer
, p_buf
, XER_coding
, 0, 0);
780 case TTCN_EncDec::CT_JSON
: {
781 TTCN_EncDec_ErrorContext
ec("While JSON-encoding type '%s': ", p_td
.name
);
783 TTCN_EncDec_ErrorContext::error_internal
784 ("No JSON descriptor available for type '%s'.", p_td
.name
);
785 JSON_Tokenizer
tok(va_arg(pvar
, int) != 0);
786 JSON_encode(p_td
, tok
);
787 p_buf
.put_s(tok
.get_buffer_length(), (const unsigned char*)tok
.get_buffer());
790 TTCN_error("Unknown coding method requested to encode type '%s'",
796 void INTEGER::decode(const TTCN_Typedescriptor_t
& p_td
, TTCN_Buffer
& p_buf
,
797 TTCN_EncDec::coding_t p_coding
, ...)
800 va_start(pvar
, p_coding
);
802 case TTCN_EncDec::CT_BER
: {
803 TTCN_EncDec_ErrorContext
ec("While BER-decoding type '%s': ", p_td
.name
);
804 unsigned L_form
=va_arg(pvar
, unsigned);
806 BER_decode_str2TLV(p_buf
, tlv
, L_form
);
807 BER_decode_TLV(p_td
, tlv
, L_form
);
808 if(tlv
.isComplete
) p_buf
.increase_pos(tlv
.get_len());
810 case TTCN_EncDec::CT_RAW
: {
811 TTCN_EncDec_ErrorContext
ec("While RAW-decoding type '%s': ", p_td
.name
);
813 TTCN_EncDec_ErrorContext::error_internal
814 ("No RAW descriptor available for type '%s'.", p_td
.name
);
816 switch(p_td
.raw
->top_bit_order
){
824 if(RAW_decode(p_td
, p_buf
, p_buf
.get_len()*8, order
)<0)
825 ec
.error(TTCN_EncDec::ET_INCOMPL_MSG
,
826 "Can not decode type '%s', because invalid or incomplete"
827 " message was received"
830 case TTCN_EncDec::CT_TEXT
: {
831 Limit_Token_List limit
;
832 TTCN_EncDec_ErrorContext
ec("While TEXT-decoding type '%s': ", p_td
.name
);
834 TTCN_EncDec_ErrorContext::error_internal
835 ("No TEXT descriptor available for type '%s'.", p_td
.name
);
836 const unsigned char *b
=p_buf
.get_data();
837 if(b
[p_buf
.get_len()-1]!='\0'){
838 p_buf
.set_pos(p_buf
.get_len());
839 p_buf
.put_zero(8,ORDER_LSB
);
842 if(TEXT_decode(p_td
,p_buf
,limit
)<0)
843 ec
.error(TTCN_EncDec::ET_INCOMPL_MSG
,
844 "Can not decode type '%s', because invalid or incomplete"
845 " message was received"
848 case TTCN_EncDec::CT_XER
: {
849 TTCN_EncDec_ErrorContext
ec("While XER-decoding type '%s': ", p_td
.name
);
850 unsigned XER_coding
=va_arg(pvar
, unsigned);
851 XmlReaderWrap
reader(p_buf
);
852 for (int success
= reader
.Read(); success
==1; success
=reader
.Read()) {
853 int type
= reader
.NodeType();
854 if (type
==XML_READER_TYPE_ELEMENT
)
857 XER_decode(*p_td
.xer
, reader
, XER_coding
, 0);
858 size_t bytes
= reader
.ByteConsumed();
859 p_buf
.set_pos(bytes
);
861 case TTCN_EncDec::CT_JSON
: {
862 TTCN_EncDec_ErrorContext
ec("While JSON-decoding type '%s': ", p_td
.name
);
864 TTCN_EncDec_ErrorContext::error_internal
865 ("No JSON descriptor available for type '%s'.", p_td
.name
);
866 JSON_Tokenizer
tok((const char*)p_buf
.get_data(), p_buf
.get_len());
867 if(JSON_decode(p_td
, tok
, false)<0)
868 ec
.error(TTCN_EncDec::ET_INCOMPL_MSG
,
869 "Can not decode type '%s', because invalid or incomplete"
870 " message was received"
872 p_buf
.set_pos(tok
.get_buf_pos());
875 TTCN_error("Unknown coding method requested to decode type '%s'",
881 ASN_BER_TLV_t
*INTEGER::BER_encode_TLV(const TTCN_Typedescriptor_t
& p_td
,
882 unsigned p_coding
) const
885 ASN_BER_TLV_t
*new_tlv
= BER_encode_chk_bound(is_bound());
888 new_tlv
= BER_encode_TLV_INTEGER(p_coding
, val
.native
);
891 int_val_t
*tmp
= new int_val_t(BN_dup(val
.openssl
));
892 new_tlv
= BER_encode_TLV_INTEGER(p_coding
, *tmp
);
896 new_tlv
= ASN_BER_V2TLV(new_tlv
, p_td
, p_coding
);
900 boolean
INTEGER::BER_decode_TLV(const TTCN_Typedescriptor_t
& p_td
,
901 const ASN_BER_TLV_t
& p_tlv
,
907 ASN_BER_TLV_t stripped_tlv
;
908 BER_decode_strip_tags(*p_td
.ber
, p_tlv
, L_form
, stripped_tlv
);
909 TTCN_EncDec_ErrorContext
ec("While decoding INTEGER type: ");
911 boolean ret_val
= BER_decode_TLV_INTEGER(stripped_tlv
, L_form
, tmp
);
912 if (tmp
.is_native()) {
914 val
.native
= tmp
.get_val();
917 val
.openssl
= BN_dup(tmp
.get_val_openssl());
919 if (ret_val
) bound_flag
= TRUE
;
923 int INTEGER::TEXT_decode(const TTCN_Typedescriptor_t
& p_td
,
924 TTCN_Buffer
& buff
, Limit_Token_List
& limit
, boolean no_err
, boolean
/*first_call*/)
926 int decoded_length
= 0;
928 if (p_td
.text
->begin_decode
) {
930 if ((tl
= p_td
.text
->begin_decode
->match_begin(buff
)) < 0) {
931 if (no_err
) return -1;
932 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_TOKEN_ERR
,
933 "The specified token '%s' not found for '%s': ",
934 (const char*)*(p_td
.text
->begin_decode
), p_td
.name
);
937 decoded_length
+= tl
;
938 buff
.increase_pos(tl
);
940 if (buff
.get_read_len() <= 1 && no_err
) return -TTCN_EncDec::ET_LEN_ERR
;
941 if (p_td
.text
->select_token
) {
943 if ((tl
= p_td
.text
->select_token
->match_begin(buff
)) < 0) {
944 if (no_err
) return -1;
948 } else if ( p_td
.text
->val
.parameters
949 && p_td
.text
->val
.parameters
->decoding_params
.min_length
!= -1) {
950 str_len
= p_td
.text
->val
.parameters
->decoding_params
.min_length
;
951 } else if (p_td
.text
->end_decode
) {
953 if ((tl
= p_td
.text
->end_decode
->match_first(buff
)) < 0) {
954 if (no_err
) return -1;
958 } else if (limit
.has_token()) {
960 if ((tl
= limit
.match(buff
)) < 0) {
961 if (no_err
) return -1;
967 if ((tl
= integer_value_match
.match_begin(buff
)) < 0) {
968 if (no_err
) return -1;
976 char *atm
= (char*)Malloc(str_len
+ 1); // sizeof(char) == 1 by definition
977 const char *b
= (const char*)buff
.get_read_data();
978 memcpy(atm
, b
, str_len
);
983 int neg
= *atm
== 0x2d ? 1 : 0;
985 for (offs
= neg
; *(atm
+ offs
) == 0x30; offs
++) ; // E.g. 0, -0, 00001234, -00001234.
986 if (neg
&& offs
> 1) *(atm
+ offs
- 1) = *atm
; // E.g. -00001234 -> -000-1234.
989 for(; atm
[offs
] == 0x20; offs
++) ;
992 if (0 == strlen(atm
+ offs
) || 0 == from_string(atm
+offs
)) {
998 buff
.increase_pos(str_len
);
999 decoded_length
+= str_len
;
1004 if (no_err
) return -1;
1005 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_TOKEN_ERR
,
1006 "Can not decode a valid integer for '%s': ", p_td
.name
);
1008 if (p_td
.text
->end_decode
) {
1010 if ((tl
= p_td
.text
->end_decode
->match_begin(buff
)) < 0) {
1011 if (no_err
) return -1;
1012 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_TOKEN_ERR
,
1013 "The specified token '%s' not found for '%s': ",
1014 (const char*)*(p_td
.text
->end_decode
), p_td
.name
);
1017 decoded_length
+= tl
;
1018 buff
.increase_pos(tl
);
1021 return decoded_length
;
1024 int INTEGER::TEXT_encode(const TTCN_Typedescriptor_t
& p_td
,
1025 TTCN_Buffer
& buff
) const
1027 int encoded_length
= 0;
1028 if (p_td
.text
->begin_encode
) {
1029 buff
.put_cs(*p_td
.text
->begin_encode
);
1030 encoded_length
+= p_td
.text
->begin_encode
->lengthof();
1033 TTCN_EncDec_ErrorContext::error
1034 (TTCN_EncDec::ET_UNBOUND
,"Encoding an unbound value.");
1035 if (p_td
.text
->end_encode
) {
1036 buff
.put_cs(*p_td
.text
->end_encode
);
1037 encoded_length
+=p_td
.text
->end_encode
->lengthof();
1039 return encoded_length
;
1043 if (native_flag
) tmp_str
= mprintf("%d", val
.native
);
1044 else tmp_str
= BN_bn2dec(val
.openssl
);
1045 CHARSTRING
ch(tmp_str
);
1046 if (native_flag
) Free(tmp_str
);
1047 else OPENSSL_free(tmp_str
);
1048 if (p_td
.text
->val
.parameters
== NULL
) {
1050 encoded_length
+= ch
.lengthof();
1052 TTCN_TEXTdescriptor_values params
= p_td
.text
->val
.parameters
1054 if (params
.min_length
< 0) {
1056 encoded_length
+= ch
.lengthof();
1058 unsigned char *p
= NULL
;
1060 size_t len
= params
.min_length
+ 1;
1061 buff
.get_end(p
, len
);
1062 if (params
.leading_zero
) {
1064 a
= snprintf((char*)p
, len
, "%0*d", params
.min_length
, val
.native
);
1066 int chlen
= ch
.lengthof(), pad
= 0;
1067 int neg
= native_flag
? (val
.native
< 0) : BN_is_negative(val
.openssl
);
1068 if (params
.min_length
> chlen
)
1069 pad
= params
.min_length
- chlen
+ neg
;
1072 memset(p
+ neg
, 0x30, pad
);
1073 for (int i
= 0; i
< chlen
- neg
; i
++)
1074 p
[i
+ pad
] = ch
[i
+ neg
].get_char();
1075 a
+= pad
+ chlen
- neg
;
1078 a
= snprintf((char*)p
, len
, "%*s", p_td
.text
->val
.parameters
->
1079 coding_params
.min_length
, (const char*)ch
);
1081 buff
.increase_length(a
);
1082 encoded_length
+= a
;
1085 if (p_td
.text
->end_encode
) {
1086 buff
.put_cs(*p_td
.text
->end_encode
);
1087 encoded_length
+= p_td
.text
->end_encode
->lengthof();
1089 return encoded_length
;
1092 unsigned char INTX_MASKS
[] = { 0 /*dummy*/, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF };
1094 int INTEGER::RAW_encode(const TTCN_Typedescriptor_t
& p_td
, RAW_enc_tree
& myleaf
) const
1096 if (!native_flag
) return RAW_encode_openssl(p_td
, myleaf
);
1098 int length
; // total length, in bytes
1099 int val_bits
= 0, len_bits
= 0; // only for IntX
1100 int value
= val
.native
;
1101 boolean neg_sgbit
= (value
< 0) && (p_td
.raw
->comp
== SG_SG_BIT
);
1103 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND
,
1104 "Encoding an unbound value.");
1108 if (value
!= 0 && value
== -value
) {
1109 // value == -INT_MAX-1 a.k.a. INT_MIN a.k.a. 0x8000....
1110 INTEGER
big_value(to_openssl(val
.native
)); // too big for native
1111 return big_value
.RAW_encode_openssl(p_td
, myleaf
);
1113 if ((value
< 0) && (p_td
.raw
->comp
== SG_NO
)) {
1114 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_SIGN_ERR
,
1115 "Unsigned encoding of a negative number: %s", p_td
.name
);
1118 if (neg_sgbit
) value
= -value
;
1119 //myleaf.ext_bit=EXT_BIT_NO;
1120 if (myleaf
.must_free
) Free(myleaf
.body
.leaf
.data_ptr
);
1121 if (p_td
.raw
->fieldlength
== RAW_INTX
) { // IntX (variable length)
1122 val_bits
= (p_td
.raw
->comp
!= SG_NO
); // bits needed to store the value
1124 if (v2
< 0 && p_td
.raw
->comp
== SG_2COMPL
) {
1132 len_bits
= 1 + val_bits
/ 8; // bits needed to store the length
1133 if (val_bits
% 8 + len_bits
% 8 > 8) {
1134 // the remainder of the value bits and the length bits do not fit into
1135 // an octet => an extra octet is needed and the length must be increased
1138 length
= (len_bits
+ val_bits
+ 7) / 8;
1139 if (len_bits
% 8 == 0 && val_bits
% 8 != 0) {
1140 // special case: the value can be stored on 8k - 1 octets plus the partial octet
1141 // - len_bits = 8k is not enough, since there's no partial octet in that case
1142 // and the length would then be followed by 8k octets (and it only indicates
1143 // 8k - 1 further octets)
1144 // - len_bits = 8k + 1 is too much, since there are only 8k - 1 octets
1145 // following the partial octet (and 8k are indicated)
1146 // solution: len_bits = 8k + 1 and insert an extra empty octet
1151 else { // not IntX, use the field length
1152 length
= (p_td
.raw
->fieldlength
+ 7) / 8;
1153 if (min_bits(value
) > p_td
.raw
->fieldlength
) {
1154 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_LEN_ERR
,
1155 "There are insufficient bits to encode '%s' : ", p_td
.name
);
1156 value
= 0; // substitute with zero
1159 if (length
> RAW_INT_ENC_LENGTH
) { // does not fit in the small buffer
1160 myleaf
.body
.leaf
.data_ptr
= bc
= (unsigned char*)Malloc(length
* sizeof(*bc
));
1161 myleaf
.must_free
= TRUE
;
1162 myleaf
.data_ptr_used
= TRUE
;
1164 else bc
= myleaf
.body
.leaf
.data_array
;
1165 if (p_td
.raw
->fieldlength
== RAW_INTX
) {
1167 // treat the empty space between the value and the length as if it was part
1168 // of the value, too
1169 val_bits
= length
* 8 - len_bits
;
1170 // first, encode the value
1172 bc
[i
] = value
& INTX_MASKS
[val_bits
> 8 ? 8 : val_bits
];
1177 while (val_bits
> 0);
1179 // the sign bit is the first bit after the length
1180 unsigned char mask
= 0x80 >> len_bits
% 8;
1183 // second, encode the length (ignore the last zero)
1185 if (val_bits
!= 0) {
1186 // the remainder of the length is in the same octet as the remainder of the
1187 // value => step back onto it
1191 // the remainder of the length is in a separate octet
1194 // insert the length's partial octet
1195 unsigned char mask
= 0x80;
1196 for (int j
= 0; j
< len_bits
% 8; ++j
) {
1200 if (len_bits
% 8 > 0 || val_bits
!= 0) {
1201 // there was a partial octet => step onto the first full octet
1204 // insert the length's full octets
1205 while (len_bits
>= 8) {
1206 // octets containing only ones in the length
1211 myleaf
.length
= length
* 8;
1214 for (int a
= 0; a
< length
; a
++) {
1215 bc
[a
] = value
& 0xFF;
1219 unsigned char mask
= 0x01 << (p_td
.raw
->fieldlength
- 1) % 8;
1220 bc
[length
- 1] |= mask
;
1222 myleaf
.length
= p_td
.raw
->fieldlength
;
1224 return myleaf
.length
;
1227 int INTEGER::RAW_encode_openssl(const TTCN_Typedescriptor_t
& p_td
,
1228 RAW_enc_tree
& myleaf
) const
1230 unsigned char *bc
= NULL
;
1231 int length
; // total length, in bytes
1232 int val_bits
= 0, len_bits
= 0; // only for IntX
1233 BIGNUM
*D
= BN_new();
1234 BN_copy(D
, val
.openssl
);
1235 boolean neg_sgbit
= (D
->neg
) && (p_td
.raw
->comp
== SG_SG_BIT
);
1237 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND
,
1238 "Encoding an unbound value.");
1242 if ((D
->neg
) && (p_td
.raw
->comp
== SG_NO
)) {
1243 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_SIGN_ERR
,
1244 "Unsigned encoding of a negative number: %s", p_td
.name
);
1245 BN_set_negative(D
, 0);
1248 // `if (neg_sgbit) tmp->neg = tmp->neg == 0;' is not needed, because the
1249 // sign is stored separately from the number. Default encoding of negative
1250 // values in 2's complement form.
1251 if (myleaf
.must_free
) Free(myleaf
.body
.leaf
.data_ptr
);
1252 if (p_td
.raw
->fieldlength
== RAW_INTX
) {
1253 val_bits
= BN_num_bits(D
) + (p_td
.raw
->comp
!= SG_NO
); // bits needed to store the value
1254 len_bits
= 1 + val_bits
/ 8; // bits needed to store the length
1255 if (val_bits
% 8 + len_bits
% 8 > 8) {
1256 // the remainder of the value bits and the length bits do not fit into
1257 // an octet => an extra octet is needed and the length must be increased
1260 length
= (len_bits
+ val_bits
+ 7) / 8;
1261 if (len_bits
% 8 == 0 && val_bits
% 8 != 0) {
1262 // special case: the value can be stored on 8k - 1 octets plus the partial octet
1263 // - len_bits = 8k is not enough, since there's no partial octet in that case
1264 // and the length would then be followed by 8k octets (and it only indicates
1265 // 8k - 1 further octets)
1266 // - len_bits = 8k + 1 is too much, since there are only 8k - 1 octets
1267 // following the partial octet (and 8k are indicated)
1268 // solution: len_bits = 8k + 1 and insert an extra empty octet
1274 length
= (p_td
.raw
->fieldlength
+ 7) / 8;
1275 if (min_bits(D
) > p_td
.raw
->fieldlength
) {
1276 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_LEN_ERR
,
1277 "There are insufficient bits to encode '%s': ", p_td
.name
);
1278 // `tmp = -((-tmp) & BitMaskTable[min_bits(tmp)]);' doesn't make any sense
1279 // at all for negative values. Just simply clear the value.
1284 if (length
> RAW_INT_ENC_LENGTH
) {
1285 myleaf
.body
.leaf
.data_ptr
= bc
=
1286 (unsigned char *)Malloc(length
* sizeof(*bc
));
1287 myleaf
.must_free
= TRUE
;
1288 myleaf
.data_ptr_used
= TRUE
;
1290 bc
= myleaf
.body
.leaf
.data_array
;
1292 boolean twos_compl
= (D
->neg
) && !neg_sgbit
;
1293 // Conversion to 2's complement.
1295 BN_set_negative(D
, 0);
1296 for (int a
= 0; a
< D
->dmax
; a
++) D
->d
[a
] = ~D
->d
[a
];
1299 if (p_td
.raw
->fieldlength
== RAW_INTX
) {
1301 // treat the empty space between the value and the length as if it was part
1302 // of the value, too
1303 val_bits
= length
* 8 - len_bits
;
1304 // first, encode the value
1306 bc
[i
] = (D
->top
? D
->d
[0] : (twos_compl
? 0xFF : 0)) & INTX_MASKS
[val_bits
> 8 ? 8 : val_bits
];
1311 while (val_bits
> 0);
1313 // the sign bit is the first bit after the length
1314 unsigned char mask
= 0x80 >> len_bits
% 8;
1317 // second, encode the length (ignore the last zero)
1319 if (val_bits
!= 0) {
1320 // the remainder of the length is in the same octet as the remainder of the
1321 // value => step back onto it
1325 // the remainder of the length is in a separate octet
1328 // insert the length's partial octet
1329 unsigned char mask
= 0x80;
1330 for (int j
= 0; j
< len_bits
% 8; ++j
) {
1334 if (len_bits
% 8 > 0 || val_bits
!= 0) {
1335 // there was a partial octet => step onto the first full octet
1338 // insert the length's full octets
1339 while (len_bits
>= 8) {
1340 // octets containing only ones in the length
1345 myleaf
.length
= length
* 8;
1348 int num_bytes
= BN_num_bytes(D
);
1349 for (int a
= 0; a
< length
; a
++) {
1350 if (twos_compl
&& num_bytes
- 1 < a
) bc
[a
] = 0xff;
1351 else bc
[a
] = (D
->top
? D
->d
[0] : 0) & 0xff;
1355 unsigned char mask
= 0x01 << (p_td
.raw
->fieldlength
- 1) % 8;
1356 bc
[length
- 1] |= mask
;
1359 myleaf
.length
= p_td
.raw
->fieldlength
;
1361 return myleaf
.length
;
1364 int INTEGER::RAW_decode(const TTCN_Typedescriptor_t
& p_td
, TTCN_Buffer
& buff
,
1365 int limit
, raw_order_t top_bit_ord
, boolean no_err
, int /*sel_field*/,
1366 boolean
/*first_call*/)
1369 int prepaddlength
= buff
.increase_pos_padd(p_td
.raw
->prepadding
);
1370 limit
-= prepaddlength
;
1372 boolean orders
= FALSE
;
1373 if (p_td
.raw
->bitorderinoctet
== ORDER_MSB
) orders
= TRUE
;
1374 if (p_td
.raw
->bitorderinfield
== ORDER_MSB
) orders
= !orders
;
1375 cp
.bitorder
= orders
? ORDER_MSB
: ORDER_LSB
;
1377 if (p_td
.raw
->byteorder
== ORDER_MSB
) orders
= TRUE
;
1378 if (p_td
.raw
->bitorderinfield
== ORDER_MSB
) orders
= !orders
;
1379 cp
.byteorder
= orders
? ORDER_MSB
: ORDER_LSB
;
1380 cp
.fieldorder
= p_td
.raw
->fieldorder
;
1381 cp
.hexorder
= ORDER_LSB
;
1382 int decode_length
= 0;
1383 int len_bits
= 0; // only for IntX (amount of bits used to store the length)
1384 unsigned char len_data
= 0; // only for IntX (an octet used to store the length)
1385 int partial_octet_bits
= 0; // only for IntX (amount of value bits in the partial octet)
1386 if (p_td
.raw
->fieldlength
== RAW_INTX
) {
1387 // extract the length
1389 // check if at least 8 bits are available in the buffer
1392 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_LEN_ERR
,
1393 "There are not enough bits in the buffer to decode the length of IntX "
1394 "type %s (needed: %d, found: %d).", p_td
.name
, len_bits
+ 8,
1397 return -TTCN_EncDec::ET_LEN_ERR
;
1402 int nof_unread_bits
= buff
.unread_len_bit();
1403 if (nof_unread_bits
< 8) {
1405 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_INCOMPL_MSG
,
1406 "There are not enough bits in the buffer to decode the length of IntX "
1407 "type %s (needed: %d, found: %d).", p_td
.name
, len_bits
+ 8,
1408 len_bits
+ nof_unread_bits
);
1410 return -TTCN_EncDec::ET_INCOMPL_MSG
;
1413 // extract the next length octet (or partial length octet)
1414 buff
.get_b(8, &len_data
, cp
, top_bit_ord
);
1415 unsigned char mask
= 0x80;
1418 if (len_data
& mask
) {
1422 // the first zero signals the end of the length
1423 // the rest of the bits in the octet are part of the value
1424 partial_octet_bits
= (8 - len_bits
% 8) % 8;
1426 // decode_length only stores the amount of bits in full octets needed
1427 // by the value, the bits in the partial octet are stored by len_data
1428 decode_length
= 8 * (len_bits
- 1);
1432 while (len_bits
% 8 != 0);
1434 while (decode_length
== 0 && partial_octet_bits
== 0);
1437 // not IntX, use the static field length
1438 decode_length
= p_td
.raw
->fieldlength
;
1440 if (decode_length
> limit
) {
1442 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_LEN_ERR
,
1443 "There are not enough bits in the buffer to decode%s type %s (needed: %d, "
1444 "found: %d).", p_td
.raw
->fieldlength
== RAW_INTX
? " the value of IntX" : "",
1445 p_td
.name
, decode_length
, limit
);
1447 if (no_err
|| p_td
.raw
->fieldlength
== RAW_INTX
) {
1448 return -TTCN_EncDec::ET_LEN_ERR
;
1450 decode_length
= limit
;
1452 int nof_unread_bits
= buff
.unread_len_bit();
1453 if (decode_length
> nof_unread_bits
) {
1455 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_INCOMPL_MSG
,
1456 "There are not enough bits in the buffer to decode%s type %s (needed: %d, "
1457 "found: %d).", p_td
.raw
->fieldlength
== RAW_INTX
? " the value of IntX" : "",
1458 p_td
.name
, decode_length
, nof_unread_bits
);
1460 if (no_err
|| p_td
.raw
->fieldlength
== RAW_INTX
) {
1461 return -TTCN_EncDec::ET_INCOMPL_MSG
;
1463 decode_length
= nof_unread_bits
;
1466 if (decode_length
< 0) return -1;
1467 else if (decode_length
== 0 && partial_octet_bits
== 0) {
1474 unsigned char *data
= (unsigned char *) Malloc(
1475 (decode_length
+ partial_octet_bits
+ 7) / 8);
1476 buff
.get_b((size_t) decode_length
, data
, cp
, top_bit_ord
);
1477 if (partial_octet_bits
!= 0) {
1478 // in case there are value bits in the last length octet (only for IntX),
1479 // these need to be appended to the extracted data
1480 data
[decode_length
/ 8] = len_data
;
1481 decode_length
+= partial_octet_bits
;
1483 int end_pos
= decode_length
;
1484 int idx
= (end_pos
- 1) / 8;
1485 boolean negativ_num
= FALSE
;
1486 switch (p_td
.raw
->comp
) {
1488 if (data
[idx
] >> ((end_pos
- 1) % 8) & 0x01) {
1496 negativ_num
= (data
[idx
] >> ((end_pos
- 1) % 8)) & 0x01;
1504 tmp
|= data
[0] & BitMaskTable
[end_pos
];
1507 idx
= (end_pos
- 1) / 8;
1508 tmp
<<= (end_pos
- 1) % 8 + 1;
1509 tmp
|= data
[idx
--] & BitMaskTable
[(end_pos
- 1) % 8 + 1];
1510 if (decode_length
> (RInt
) sizeof(RInt
) * 8 - 1) {
1511 BIGNUM
*D
= BN_new();
1512 BN_set_word(D
, tmp
);
1513 int pad
= tmp
== 0 ? 1 : 0;
1514 for (; idx
>= 0; idx
--) {
1515 if (pad
&& data
[idx
] != 0) {
1516 BN_set_word(D
, data
[idx
] & 0xff);
1522 BN_add_word(D
, data
[idx
] & 0xff);
1525 BIGNUM
*D_tmp
= BN_new();
1526 BN_set_bit(D_tmp
, BN_num_bits(D
));
1527 BN_sub(D
, D
, D_tmp
);
1530 else if (negativ_num
) {
1531 BN_set_negative(D
, 1);
1533 // Back to native. "BN_num_bits(D) + BN_is_negative(D) >
1534 // (RInt)sizeof(RInt) * 8 - !BN_is_negative(D)" was an over-complicated
1536 if (BN_num_bits(D
) > (RInt
) sizeof(RInt
) * 8 - 1) {
1537 native_flag
= FALSE
;
1542 val
.native
= BN_is_negative(D
) ? -D
->d
[0] : D
->d
[0];
1549 for (; idx
>= 0; idx
--) {
1551 tmp
|= data
[idx
] & 0xff;
1557 val
.native
= negativ_num
? (RInt
) -tmp
: (RInt
) tmp
;
1559 end
: decode_length
+= buff
.increase_pos_padd(p_td
.raw
->padding
);
1561 return decode_length
+ prepaddlength
+ len_bits
;
1564 int INTEGER::XER_encode(const XERdescriptor_t
& p_td
, TTCN_Buffer
& p_buf
,
1565 unsigned int flavor
, int indent
, embed_values_enc_struct_t
*) const
1568 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND
,
1569 "Encoding an unbound integer value.");
1571 int encoded_length
= (int) p_buf
.get_len();
1573 flavor
|= SIMPLE_TYPE
;
1574 flavor
&= ~XER_RECOF
; // integer doesn't care
1575 if (begin_xml(p_td
, p_buf
, flavor
, indent
, false) == -1) --encoded_length
;
1579 tmp_str
= mprintf("%d", val
.native
);
1581 tmp_str
= BN_bn2dec(val
.openssl
);
1582 CHARSTRING
value(tmp_str
);
1586 OPENSSL_free(tmp_str
);
1587 p_buf
.put_string(value
);
1589 end_xml(p_td
, p_buf
, flavor
, indent
, false);
1591 return (int) p_buf
.get_len() - encoded_length
;
1594 int INTEGER::XER_decode(const XERdescriptor_t
& p_td
, XmlReaderWrap
& reader
,
1595 unsigned int flavor
, embed_values_dec_struct_t
*)
1597 const boolean exer
= is_exer(flavor
);
1598 int depth
= -1, success
= reader
.Ok(), type
;
1599 const char * value
= 0;
1601 boolean own_tag
= !(exer
&& (p_td
.xer_bits
& UNTAGGED
)) && !is_exerlist(flavor
);
1603 if (!own_tag
) goto tagless
;
1604 if (exer
&& (p_td
.xer_bits
& XER_ATTRIBUTE
)) {
1605 verify_name(reader
, p_td
, exer
);
1607 value
= (const char *)reader
.Value();
1609 for (; *value
&& isspace(*value
); ++value
) {}
1611 if (get_nof_digits() != (int)strlen(value
) - (value
[0] == '-') ? 1 : 0) {
1614 // Let the caller do reader.AdvanceAttribute();
1617 for (; success
== 1; success
= reader
.Read()) {
1618 type
= reader
.NodeType();
1619 if (XML_READER_TYPE_ELEMENT
== type
) {
1620 verify_name(reader
, p_td
, exer
);
1621 if (reader
.IsEmptyElement()) {
1622 if (exer
&& p_td
.dfeValue
!= 0) {
1623 *this = *static_cast<const INTEGER
*> (p_td
.dfeValue
);
1628 depth
= reader
.Depth();
1630 else if (XML_READER_TYPE_TEXT
== type
&& depth
!= -1) {
1631 value
= (const char*) reader
.Value();
1632 for (; *value
&& isspace(*value
); ++value
) {}
1634 if (get_nof_digits() != (int)strlen(value
) - (value
[0] == '-') ? 1 : 0) {
1638 else if (XML_READER_TYPE_END_ELEMENT
== type
) {
1639 verify_end(reader
, p_td
, depth
, exer
);
1640 if (!bound_flag
&& exer
&& p_td
.dfeValue
!= 0) {
1641 *this = *static_cast<const INTEGER
*> (p_td
.dfeValue
);
1647 } // if not attribute
1652 int INTEGER::get_nof_digits()
1656 RInt x
= val
.native
;
1657 if (x
== 0) return 1;
1664 BIGNUM
*x
= BN_new();
1665 BN_copy(x
, val
.openssl
);
1666 if (BN_is_zero(x
)) return 1;
1668 while (!BN_is_zero(x
)) {
1676 int INTEGER::JSON_encode(const TTCN_Typedescriptor_t
&, JSON_Tokenizer
& p_tok
) const
1679 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND
,
1680 "Encoding an unbound integer value.");
1685 tmp_str
= mprintf("%d", val
.native
);
1687 tmp_str
= BN_bn2dec(val
.openssl
);
1690 int enc_len
= p_tok
.put_next_token(JSON_TOKEN_NUMBER
, tmp_str
);
1695 OPENSSL_free(tmp_str
);
1701 int INTEGER::JSON_decode(const TTCN_Typedescriptor_t
& p_td
, JSON_Tokenizer
& p_tok
, boolean p_silent
)
1703 json_token_t token
= JSON_TOKEN_NONE
;
1705 size_t value_len
= 0;
1707 boolean use_default
= p_td
.json
->default_value
&& 0 == p_tok
.get_buffer_length();
1709 // No JSON data in the buffer -> use default value
1710 value
= (char*)p_td
.json
->default_value
;
1711 value_len
= strlen(value
);
1713 dec_len
= p_tok
.get_next_token(&token
, &value
, &value_len
);
1715 if (JSON_TOKEN_ERROR
== token
) {
1716 JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG
, JSON_DEC_BAD_TOKEN_ERROR
, "");
1717 return JSON_ERROR_FATAL
;
1719 else if (JSON_TOKEN_NUMBER
== token
|| use_default
) {
1720 char* number
= mcopystrn(value
, value_len
);
1721 if (from_string(number
) && (int)value_len
== get_nof_digits() + ('-' == value
[0] ? 1 : 0)) {
1724 JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG
, JSON_DEC_FORMAT_ERROR
, "number", "integer");
1726 dec_len
= JSON_ERROR_FATAL
;
1731 return JSON_ERROR_INVALID_TOKEN
;
1737 // Global functions.
1739 INTEGER
operator+(int int_value
, const INTEGER
& other_value
)
1741 other_value
.must_bound("Unbound right operand of integer addition.");
1742 return INTEGER(int_value
) + other_value
;
1745 INTEGER
operator-(int int_value
, const INTEGER
& other_value
)
1747 other_value
.must_bound("Unbound right operand of integer subtraction.");
1748 return INTEGER(int_value
) - other_value
;
1751 INTEGER
operator*(int int_value
, const INTEGER
& other_value
)
1753 other_value
.must_bound("Unbound right operand of integer multiplication.");
1754 return INTEGER(int_value
) * other_value
;
1757 INTEGER
operator/(int int_value
, const INTEGER
& other_value
)
1759 other_value
.must_bound("Unbound right operand of integer division.");
1760 if (other_value
.get_val() == 0)
1761 TTCN_error("Integer division by zero.");
1762 return INTEGER(int_value
) / other_value
;
1765 INTEGER
rem(int left_value
, int right_value
)
1767 if (right_value
== 0)
1768 TTCN_error("The right operand of rem operator is zero.");
1769 return INTEGER(left_value
- right_value
* (left_value
/ right_value
));
1772 INTEGER
rem(const INTEGER
& left_value
, const INTEGER
& right_value
)
1774 left_value
.must_bound("Unbound left operand of rem operator.");
1775 right_value
.must_bound("Unbound right operand of rem operator.");
1776 return left_value
- right_value
* (left_value
/ right_value
);
1779 INTEGER
rem(const INTEGER
& left_value
, int right_value
)
1781 left_value
.must_bound("Unbound left operand of rem operator.");
1782 return rem(left_value
, INTEGER(right_value
));
1785 INTEGER
rem(int left_value
, const INTEGER
& right_value
)
1787 right_value
.must_bound("Unbound right operand of rem operator.");
1788 return rem(INTEGER(left_value
), right_value
);
1791 INTEGER
mod(int left_value
, int right_value
)
1793 if (right_value
< 0) right_value
= -right_value
;
1794 else if (right_value
== 0)
1795 TTCN_error("The right operand of mod operator is zero.");
1796 if (left_value
> 0) return rem(left_value
, right_value
);
1798 int result
= rem(left_value
, right_value
);
1799 if (result
== 0) return 0;
1800 else return INTEGER(right_value
+ result
);
1804 INTEGER
mod(const INTEGER
& left_value
, const INTEGER
& right_value
)
1806 left_value
.must_bound("Unbound left operand of mod operator.");
1807 right_value
.must_bound("Unbound right operand of mod operator.");
1808 INTEGER
right_value_abs(right_value
);
1809 if (right_value
< 0) right_value_abs
= -right_value_abs
;
1810 else if (right_value
== 0)
1811 TTCN_error("The right operand of mod operator is zero.");
1812 if (left_value
> 0) {
1813 return rem(left_value
, right_value_abs
);
1815 INTEGER result
= rem(left_value
, right_value_abs
);
1816 if (result
== 0) return INTEGER((int)0);
1817 else return INTEGER(right_value_abs
+ result
);
1821 INTEGER
mod(const INTEGER
& left_value
, int right_value
)
1823 left_value
.must_bound("Unbound left operand of mod operator.");
1824 return mod(left_value
, INTEGER(right_value
));
1827 INTEGER
mod(int left_value
, const INTEGER
& right_value
)
1829 right_value
.must_bound("Unbound right operand of mod operator.");
1830 return mod(INTEGER(left_value
), right_value
);
1833 boolean
operator==(int int_value
, const INTEGER
& other_value
)
1835 other_value
.must_bound("Unbound right operand of integer comparison.");
1836 return INTEGER(int_value
) == other_value
;
1839 boolean
operator<(int int_value
, const INTEGER
& other_value
)
1841 other_value
.must_bound("Unbound right operand of integer comparison.");
1842 return INTEGER(int_value
) < other_value
;
1845 boolean
operator>(int int_value
, const INTEGER
& other_value
)
1847 other_value
.must_bound("Unbound right operand of integer comparison.");
1848 return INTEGER(int_value
) > other_value
;
1851 // Integer template class.
1853 void INTEGER_template::clean_up()
1855 switch (template_selection
) {
1856 case SPECIFIC_VALUE
:
1857 if (unlikely(!int_val
.native_flag
)) BN_free(int_val
.val
.openssl
);
1860 case COMPLEMENTED_LIST
:
1861 delete [] value_list
.list_value
;
1864 if (value_range
.min_is_present
&& unlikely(!value_range
.min_value
.native_flag
))
1865 BN_free(value_range
.min_value
.val
.openssl
);
1866 if (value_range
.max_is_present
&& unlikely(!value_range
.max_value
.native_flag
))
1867 BN_free(value_range
.max_value
.val
.openssl
);
1872 template_selection
= UNINITIALIZED_TEMPLATE
;
1875 void INTEGER_template::copy_template(const INTEGER_template
& other_value
)
1877 switch (other_value
.template_selection
) {
1878 case SPECIFIC_VALUE
:
1879 int_val
.native_flag
= other_value
.int_val
.native_flag
;
1880 if (likely(int_val
.native_flag
))
1881 int_val
.val
.native
= other_value
.int_val
.val
.native
;
1882 else int_val
.val
.openssl
= BN_dup(other_value
.int_val
.val
.openssl
);
1889 case COMPLEMENTED_LIST
:
1890 value_list
.n_values
= other_value
.value_list
.n_values
;
1891 value_list
.list_value
= new INTEGER_template
[value_list
.n_values
];
1892 for (unsigned int i
= 0; i
< value_list
.n_values
; i
++)
1893 value_list
.list_value
[i
].copy_template(
1894 other_value
.value_list
.list_value
[i
]);
1897 value_range
.min_is_present
= other_value
.value_range
.min_is_present
;
1898 if (value_range
.min_is_present
) {
1899 value_range
.min_value
.native_flag
= other_value
.value_range
.min_value
.native_flag
;
1900 if (likely(value_range
.min_value
.native_flag
))
1901 value_range
.min_value
.val
.native
=
1902 other_value
.value_range
.min_value
.val
.native
;
1904 value_range
.min_value
.val
.openssl
=
1905 BN_dup(other_value
.value_range
.min_value
.val
.openssl
);
1907 value_range
.max_is_present
= other_value
.value_range
.max_is_present
;
1908 if (value_range
.max_is_present
) {
1909 value_range
.max_value
.native_flag
= other_value
.value_range
.max_value
.native_flag
;
1910 if (likely(value_range
.max_value
.native_flag
))
1911 value_range
.max_value
.val
.native
=
1912 other_value
.value_range
.max_value
.val
.native
;
1914 value_range
.max_value
.val
.openssl
=
1915 BN_dup(other_value
.value_range
.max_value
.val
.openssl
);
1919 TTCN_error("Copying an uninitialized/unsupported integer template.");
1921 set_selection(other_value
);
1924 INTEGER_template::INTEGER_template()
1928 INTEGER_template::INTEGER_template(template_sel other_value
)
1929 : Base_Template(other_value
)
1931 check_single_selection(other_value
);
1934 INTEGER_template::INTEGER_template(int other_value
)
1935 : Base_Template(SPECIFIC_VALUE
)
1937 int_val
.native_flag
= TRUE
;
1938 int_val
.val
.native
= other_value
;
1941 INTEGER_template::INTEGER_template(const INTEGER
& other_value
)
1942 : Base_Template(SPECIFIC_VALUE
)
1944 other_value
.must_bound("Creating a template from an unbound integer "
1946 int_val_t other_value_int
= other_value
.get_val();
1947 int_val
.native_flag
= other_value_int
.native_flag
;
1948 if (likely(int_val
.native_flag
))
1949 int_val
.val
.native
= other_value_int
.val
.native
;
1950 else int_val
.val
.openssl
= BN_dup(other_value_int
.val
.openssl
);
1953 INTEGER_template::INTEGER_template(const OPTIONAL
<INTEGER
>& other_value
)
1955 switch (other_value
.get_selection()) {
1956 case OPTIONAL_PRESENT
: {
1957 set_selection(SPECIFIC_VALUE
);
1958 int_val_t other_value_int
= ((const INTEGER
&)other_value
).get_val();
1959 int_val
.native_flag
= other_value_int
.native_flag
;
1960 if (likely(int_val
.native_flag
))
1961 int_val
.val
.native
= other_value_int
.val
.native
;
1962 else int_val
.val
.openssl
= BN_dup(other_value_int
.val
.openssl
);
1965 set_selection(OMIT_VALUE
);
1968 TTCN_error("Creating an integer template from an unbound optional field.");
1972 INTEGER_template::INTEGER_template(const INTEGER_template
& other_value
)
1975 copy_template(other_value
);
1978 INTEGER_template::~INTEGER_template()
1983 INTEGER_template
& INTEGER_template::operator=(template_sel other_value
)
1985 check_single_selection(other_value
);
1987 set_selection(other_value
);
1991 INTEGER_template
& INTEGER_template::operator=(int other_value
)
1994 set_selection(SPECIFIC_VALUE
);
1995 int_val
.native_flag
= TRUE
;
1996 int_val
.val
.native
= other_value
;
2000 INTEGER_template
& INTEGER_template::operator=(const INTEGER
& other_value
)
2002 other_value
.must_bound("Assignment of an unbound integer value to a "
2005 set_selection(SPECIFIC_VALUE
);
2006 int_val_t other_value_int
= other_value
.get_val();
2007 int_val
.native_flag
= other_value_int
.native_flag
;
2008 if (likely(int_val
.native_flag
))
2009 int_val
.val
.native
= other_value_int
.val
.native
;
2010 else int_val
.val
.openssl
= BN_dup(other_value_int
.val
.openssl
);
2014 INTEGER_template
& INTEGER_template::operator=
2015 (const OPTIONAL
<INTEGER
>& other_value
)
2018 switch (other_value
.get_selection()) {
2019 case OPTIONAL_PRESENT
: {
2020 set_selection(SPECIFIC_VALUE
);
2021 int_val_t other_value_int
= ((const INTEGER
&)other_value
).get_val();
2022 int_val
.native_flag
= other_value_int
.native_flag
;
2023 if (likely(int_val
.native_flag
))
2024 int_val
.val
.native
= other_value_int
.val
.native
;
2025 else int_val
.val
.openssl
= BN_dup(other_value_int
.val
.openssl
);
2028 set_selection(OMIT_VALUE
);
2031 TTCN_error("Assignment of an unbound optional field to an integer "
2037 INTEGER_template
& INTEGER_template::operator=
2038 (const INTEGER_template
& other_value
)
2040 if (&other_value
!= this) {
2042 copy_template(other_value
);
2047 boolean
INTEGER_template::match(int other_value
, boolean
/* legacy */) const
2049 switch (template_selection
) {
2050 case SPECIFIC_VALUE
:
2051 if (likely(int_val
.native_flag
)) return int_val
.val
.native
== other_value
;
2052 return int_val_t(BN_dup(int_val
.val
.openssl
)) == other_value
;
2059 case COMPLEMENTED_LIST
:
2060 for(unsigned int i
= 0; i
< value_list
.n_values
; i
++)
2061 if (value_list
.list_value
[i
].match(other_value
))
2062 return template_selection
== VALUE_LIST
;
2063 return template_selection
== COMPLEMENTED_LIST
;
2065 boolean lower_boundary
= !value_range
.min_is_present
;
2066 boolean upper_boundary
= !value_range
.max_is_present
;
2067 // Lower boundary is set.
2068 if (!lower_boundary
) {
2069 lower_boundary
= (likely(value_range
.min_value
.native_flag
) ?
2070 int_val_t(value_range
.min_value
.val
.native
) :
2071 int_val_t(BN_dup(value_range
.min_value
.val
.openssl
))) <= other_value
;
2073 // Upper boundary is set.
2074 if (!upper_boundary
) {
2075 upper_boundary
= (likely(value_range
.max_value
.native_flag
) ?
2076 int_val_t(value_range
.max_value
.val
.native
) :
2077 int_val_t(BN_dup(value_range
.max_value
.val
.openssl
))) >= other_value
;
2079 return lower_boundary
&& upper_boundary
; }
2081 TTCN_error("Matching with an uninitialized/unsupported integer "
2087 boolean
INTEGER_template::match(const INTEGER
& other_value
,
2088 boolean
/* legacy */) const
2090 if (!other_value
.is_bound()) return FALSE
;
2091 switch (template_selection
) {
2092 case SPECIFIC_VALUE
: {
2093 int_val_t int_val_int
= likely(int_val
.native_flag
) ?
2094 int_val_t(int_val
.val
.native
) : int_val_t(BN_dup(int_val
.val
.openssl
));
2095 return int_val_int
== other_value
.get_val(); }
2102 case COMPLEMENTED_LIST
: // Merged cases.
2103 for (unsigned int i
= 0; i
< value_list
.n_values
; i
++)
2104 if (value_list
.list_value
[i
].match(other_value
))
2105 return template_selection
== VALUE_LIST
;
2106 return template_selection
== COMPLEMENTED_LIST
;
2108 boolean lower_boundary
= !value_range
.min_is_present
;
2109 boolean upper_boundary
= !value_range
.max_is_present
;
2110 // Lower boundary is set.
2111 if (!lower_boundary
) {
2112 lower_boundary
= (likely(value_range
.min_value
.native_flag
) ?
2113 int_val_t(value_range
.min_value
.val
.native
) :
2114 int_val_t(BN_dup(value_range
.min_value
.val
.openssl
))) <= other_value
.get_val();
2116 // Upper boundary is set.
2117 if (!upper_boundary
) {
2118 upper_boundary
= (likely(value_range
.max_value
.native_flag
) ?
2119 int_val_t(value_range
.max_value
.val
.native
) :
2120 int_val_t(BN_dup(value_range
.max_value
.val
.openssl
))) >= other_value
.get_val();
2122 return lower_boundary
&& upper_boundary
; }
2124 TTCN_error("Matching with an uninitialized/unsupported integer "
2130 INTEGER
INTEGER_template::valueof() const
2132 if (template_selection
!= SPECIFIC_VALUE
|| is_ifpresent
)
2133 TTCN_error("Performing a valueof or send operation on a non-specific "
2134 "integer template.");
2135 if (likely(int_val
.native_flag
)) return INTEGER(int_val
.val
.native
);
2136 else return INTEGER(BN_dup(int_val
.val
.openssl
));
2139 void INTEGER_template::set_type(template_sel template_type
,
2140 unsigned int list_length
)
2143 switch (template_type
) {
2145 case COMPLEMENTED_LIST
:
2146 set_selection(template_type
);
2147 value_list
.n_values
= list_length
;
2148 value_list
.list_value
= new INTEGER_template
[list_length
];
2151 set_selection(VALUE_RANGE
);
2152 value_range
.min_is_present
= FALSE
;
2153 value_range
.max_is_present
= FALSE
;
2156 TTCN_error("Setting an invalid type for an integer template.");
2160 INTEGER_template
& INTEGER_template::list_item(unsigned int list_index
)
2162 if (template_selection
!= VALUE_LIST
&&
2163 template_selection
!= COMPLEMENTED_LIST
)
2164 TTCN_error("Accessing a list element of a non-list integer template.");
2165 if (list_index
>= value_list
.n_values
)
2166 TTCN_error("Index overflow in an integer value list template.");
2167 return value_list
.list_value
[list_index
];
2170 void INTEGER_template::set_min(int min_value
)
2172 if (template_selection
!= VALUE_RANGE
)
2173 TTCN_error("Integer template is not range when setting lower limit.");
2174 if (value_range
.max_is_present
) {
2175 int_val_t max_value_int
= likely(value_range
.max_value
.native_flag
) ?
2176 int_val_t(value_range
.max_value
.val
.native
) :
2177 int_val_t(BN_dup(value_range
.max_value
.val
.openssl
));
2178 if (max_value_int
< min_value
)
2179 TTCN_error("The lower limit of the range is greater than the upper "
2180 "limit in an integer template.");
2182 value_range
.min_is_present
= TRUE
;
2183 value_range
.min_value
.native_flag
= TRUE
;
2184 value_range
.min_value
.val
.native
= min_value
;
2187 void INTEGER_template::set_min(const INTEGER
& min_value
)
2189 // Redundant, but performace matters. :)
2190 min_value
.must_bound("Using an unbound value when setting the lower bound "
2191 "in an integer range template.");
2192 if (template_selection
!= VALUE_RANGE
)
2193 TTCN_error("Integer template is not range when setting lower limit.");
2194 int_val_t min_value_int
= min_value
.get_val();
2195 if (value_range
.max_is_present
) {
2196 int_val_t max_value_int
= likely(value_range
.max_value
.native_flag
) ?
2197 int_val_t(value_range
.max_value
.val
.native
) :
2198 int_val_t(BN_dup(value_range
.max_value
.val
.openssl
));
2199 if (max_value_int
< min_value_int
)
2200 TTCN_error("The lower limit of the range is greater than the upper "
2201 "limit in an integer template.");
2203 value_range
.min_is_present
= TRUE
;
2204 value_range
.min_value
.native_flag
= min_value_int
.native_flag
;
2205 if (likely(value_range
.min_value
.native_flag
))
2206 value_range
.min_value
.val
.native
= min_value_int
.val
.native
;
2207 else value_range
.min_value
.val
.openssl
= BN_dup(min_value_int
.val
.openssl
);
2210 void INTEGER_template::set_max(int max_value
)
2212 if (template_selection
!= VALUE_RANGE
)
2213 TTCN_error("Integer template is not range when setting upper limit.");
2214 if (value_range
.min_is_present
) {
2215 int_val_t min_value_int
= likely(value_range
.min_value
.native_flag
) ?
2216 int_val_t(value_range
.min_value
.val
.native
) :
2217 int_val_t(BN_dup(value_range
.min_value
.val
.openssl
));
2218 if (min_value_int
> max_value
)
2219 TTCN_error("The upper limit of the range is smaller than the lower "
2220 "limit in an integer template.");
2222 value_range
.max_is_present
= TRUE
;
2223 value_range
.max_value
.native_flag
= TRUE
;
2224 value_range
.max_value
.val
.native
= max_value
;
2227 void INTEGER_template::set_max(const INTEGER
& max_value
)
2229 max_value
.must_bound("Using an unbound value when setting the upper bound "
2230 "in an integer range template.");
2231 if (template_selection
!= VALUE_RANGE
)
2232 TTCN_error("Integer template is not range when setting upper limit.");
2233 int_val_t max_value_int
= max_value
.get_val();
2234 if (value_range
.min_is_present
) {
2235 int_val_t min_value_int
= likely(value_range
.min_value
.native_flag
) ?
2236 int_val_t(value_range
.min_value
.val
.native
) :
2237 int_val_t(BN_dup(value_range
.min_value
.val
.openssl
));
2238 if (min_value_int
> max_value_int
)
2239 TTCN_error("The upper limit of the range is smaller than the lower "
2240 "limit in an integer template.");
2242 value_range
.max_is_present
= TRUE
;
2243 value_range
.max_value
.native_flag
= max_value_int
.native_flag
;
2244 if (likely(value_range
.max_value
.native_flag
))
2245 value_range
.max_value
.val
.native
= max_value_int
.val
.native
;
2246 else value_range
.max_value
.val
.openssl
= BN_dup(max_value_int
.val
.openssl
);
2249 void INTEGER_template::log() const
2251 switch (template_selection
) {
2252 case SPECIFIC_VALUE
: {
2253 int_val_t int_val_int
= likely(int_val
.native_flag
) ?
2254 int_val_t(int_val
.val
.native
) : int_val_t(BN_dup(int_val
.val
.openssl
));
2255 char *tmp_str
= int_val_int
.as_string();
2256 TTCN_Logger::log_event("%s", tmp_str
);
2259 case COMPLEMENTED_LIST
:
2260 TTCN_Logger::log_event_str("complement ");
2263 TTCN_Logger::log_char('(');
2264 for (unsigned int i
= 0; i
< value_list
.n_values
; i
++) {
2265 if (i
> 0) TTCN_Logger::log_event_str(", ");
2266 value_list
.list_value
[i
].log();
2268 TTCN_Logger::log_char(')');
2271 TTCN_Logger::log_char('(');
2272 if (value_range
.min_is_present
) {
2273 int_val_t min_value_int
= likely(value_range
.min_value
.native_flag
) ?
2274 int_val_t(value_range
.min_value
.val
.native
) :
2275 int_val_t(BN_dup(value_range
.min_value
.val
.openssl
));
2276 char *min_str
= min_value_int
.as_string();
2277 TTCN_Logger::log_event("%s", min_str
);
2280 TTCN_Logger::log_event_str("-infinity");
2282 TTCN_Logger::log_event_str(" .. ");
2283 if (value_range
.max_is_present
) {
2284 int_val_t max_value_int
= likely(value_range
.max_value
.native_flag
) ?
2285 int_val_t(value_range
.max_value
.val
.native
) :
2286 int_val_t(BN_dup(value_range
.max_value
.val
.openssl
));
2287 char *max_str
= max_value_int
.as_string();
2288 TTCN_Logger::log_event("%s", max_str
);
2291 TTCN_Logger::log_event_str("infinity");
2293 TTCN_Logger::log_char(')');
2302 void INTEGER_template::log_match(const INTEGER
& match_value
,
2303 boolean
/* legacy */) const
2305 if (TTCN_Logger::VERBOSITY_COMPACT
== TTCN_Logger::get_matching_verbosity()
2306 && TTCN_Logger::get_logmatch_buffer_len() != 0) {
2307 TTCN_Logger::print_logmatch_buffer();
2308 TTCN_Logger::log_event_str(" := ");
2311 TTCN_Logger::log_event_str(" with ");
2313 if (match(match_value
)) TTCN_Logger::log_event_str(" matched");
2314 else TTCN_Logger::log_event_str(" unmatched");
2317 void INTEGER_template::set_param(Module_Param
& param
) {
2318 param
.basic_check(Module_Param::BC_TEMPLATE
, "integer template");
2319 Module_Param_Ptr mp
= ¶m
;
2320 if (param
.get_type() == Module_Param::MP_Reference
) {
2321 mp
= param
.get_referenced_param();
2323 switch (mp
->get_type()) {
2324 case Module_Param::MP_Omit
:
2327 case Module_Param::MP_Any
:
2330 case Module_Param::MP_AnyOrNone
:
2331 *this = ANY_OR_OMIT
;
2333 case Module_Param::MP_List_Template
:
2334 case Module_Param::MP_ComplementList_Template
: {
2335 INTEGER_template temp
;
2336 temp
.set_type(mp
->get_type() == Module_Param::MP_List_Template
?
2337 VALUE_LIST
: COMPLEMENTED_LIST
, mp
->get_size());
2338 for (size_t i
=0; i
<mp
->get_size(); i
++) {
2339 temp
.list_item(i
).set_param(*mp
->get_elem(i
));
2343 case Module_Param::MP_Integer
: {
2345 tmp
.set_val(*mp
->get_integer());
2348 case Module_Param::MP_IntRange
: {
2349 set_type(VALUE_RANGE
);
2350 if (mp
->get_lower_int()!=NULL
) {
2352 tmp
.set_val(*mp
->get_lower_int());
2355 if (mp
->get_upper_int()!=NULL
) {
2357 tmp
.set_val(*mp
->get_upper_int());
2361 case Module_Param::MP_Expression
:
2362 switch (mp
->get_expr_type()) {
2363 case Module_Param::EXPR_NEGATE
: {
2365 operand
.set_param(*mp
->get_operand1());
2368 case Module_Param::EXPR_ADD
: {
2369 INTEGER operand1
, operand2
;
2370 operand1
.set_param(*mp
->get_operand1());
2371 operand2
.set_param(*mp
->get_operand2());
2372 *this = operand1
+ operand2
;
2374 case Module_Param::EXPR_SUBTRACT
: {
2375 INTEGER operand1
, operand2
;
2376 operand1
.set_param(*mp
->get_operand1());
2377 operand2
.set_param(*mp
->get_operand2());
2378 *this = operand1
- operand2
;
2380 case Module_Param::EXPR_MULTIPLY
: {
2381 INTEGER operand1
, operand2
;
2382 operand1
.set_param(*mp
->get_operand1());
2383 operand2
.set_param(*mp
->get_operand2());
2384 *this = operand1
* operand2
;
2386 case Module_Param::EXPR_DIVIDE
: {
2387 INTEGER operand1
, operand2
;
2388 operand1
.set_param(*mp
->get_operand1());
2389 operand2
.set_param(*mp
->get_operand2());
2390 if (operand2
== 0) {
2391 param
.error("Integer division by zero.");
2393 *this = operand1
/ operand2
;
2396 param
.expr_type_error("an integer");
2401 param
.type_error("integer template");
2403 is_ifpresent
= param
.get_ifpresent() || mp
->get_ifpresent();
2406 Module_Param
* INTEGER_template::get_param(Module_Param_Name
& param_name
) const
2408 Module_Param
* mp
= NULL
;
2409 switch (template_selection
) {
2410 case UNINITIALIZED_TEMPLATE
:
2411 mp
= new Module_Param_Unbound();
2414 mp
= new Module_Param_Omit();
2417 mp
= new Module_Param_Any();
2420 mp
= new Module_Param_AnyOrNone();
2422 case SPECIFIC_VALUE
:
2423 if (likely(int_val
.native_flag
)) {
2424 mp
= new Module_Param_Integer(new int_val_t(int_val
.val
.native
));
2427 mp
= new Module_Param_Integer(new int_val_t(BN_dup(int_val
.val
.openssl
)));
2431 case COMPLEMENTED_LIST
: {
2432 if (template_selection
== VALUE_LIST
) {
2433 mp
= new Module_Param_List_Template();
2436 mp
= new Module_Param_ComplementList_Template();
2438 for (size_t i
= 0; i
< value_list
.n_values
; ++i
) {
2439 mp
->add_elem(value_list
.list_value
[i
].get_param(param_name
));
2443 int_val_t
* lower_bound
= NULL
;
2444 int_val_t
* upper_bound
= NULL
;
2445 if (value_range
.min_is_present
) {
2446 if (value_range
.min_value
.native_flag
) {
2447 lower_bound
= new int_val_t(value_range
.min_value
.val
.native
);
2450 lower_bound
= new int_val_t(BN_dup(value_range
.min_value
.val
.openssl
));
2453 if (value_range
.max_is_present
) {
2454 if (value_range
.max_value
.native_flag
) {
2455 upper_bound
= new int_val_t(value_range
.max_value
.val
.native
);
2458 upper_bound
= new int_val_t(BN_dup(value_range
.max_value
.val
.openssl
));
2461 mp
= new Module_Param_IntRange(lower_bound
, upper_bound
);
2467 mp
->set_ifpresent();
2472 void INTEGER_template::encode_text(Text_Buf
& text_buf
) const
2474 encode_text_base(text_buf
);
2475 switch (template_selection
) {
2480 case SPECIFIC_VALUE
:
2481 text_buf
.push_int(likely(int_val
.native_flag
) ? int_val_t(int_val
.val
.native
)
2482 : int_val_t(BN_dup(int_val
.val
.openssl
)));
2485 case COMPLEMENTED_LIST
:
2486 text_buf
.push_int(value_list
.n_values
);
2487 for (unsigned int i
= 0; i
< value_list
.n_values
; i
++)
2488 value_list
.list_value
[i
].encode_text(text_buf
);
2491 text_buf
.push_int(value_range
.min_is_present
? 1 : 0);
2492 if (value_range
.min_is_present
)
2493 text_buf
.push_int(likely(value_range
.min_value
.native_flag
) ?
2494 int_val_t(value_range
.min_value
.val
.native
) :
2495 int_val_t(BN_dup(value_range
.min_value
.val
.openssl
)));
2496 text_buf
.push_int(value_range
.max_is_present
? 1 : 0);
2497 if (value_range
.max_is_present
)
2498 text_buf
.push_int(likely(value_range
.max_value
.native_flag
) ?
2499 int_val_t(value_range
.max_value
.val
.native
) :
2500 int_val_t(BN_dup(value_range
.max_value
.val
.openssl
)));
2503 TTCN_error("Text encoder: Encoding an uninitialized/unsupported integer "
2508 void INTEGER_template::decode_text(Text_Buf
& text_buf
)
2511 decode_text_base(text_buf
);
2512 switch (template_selection
) {
2517 case SPECIFIC_VALUE
: {
2518 int_val_t int_val_int
= text_buf
.pull_int();
2519 int_val
.native_flag
= int_val_int
.native_flag
;
2520 if (likely(int_val
.native_flag
)) int_val
.val
.native
= int_val_int
.val
.native
;
2521 else int_val
.val
.openssl
= BN_dup(int_val_int
.val
.openssl
);
2524 case COMPLEMENTED_LIST
:
2525 value_list
.n_values
= text_buf
.pull_int().get_val();
2526 value_list
.list_value
= new INTEGER_template
[value_list
.n_values
];
2527 for (unsigned int i
= 0; i
< value_list
.n_values
; i
++)
2528 value_list
.list_value
[i
].decode_text(text_buf
);
2531 value_range
.min_is_present
= text_buf
.pull_int() != 0;
2532 if (value_range
.min_is_present
) {
2533 int_val_t min_value_int
= text_buf
.pull_int();
2534 value_range
.min_value
.native_flag
= min_value_int
.native_flag
;
2535 if (likely(value_range
.min_value
.native_flag
))
2536 value_range
.min_value
.val
.native
= min_value_int
.val
.native
;
2537 else value_range
.min_value
.val
.openssl
= BN_dup(min_value_int
.val
.openssl
);
2539 value_range
.max_is_present
= text_buf
.pull_int() != 0;
2540 if (value_range
.max_is_present
) {
2541 int_val_t max_value_int
= text_buf
.pull_int();
2542 value_range
.max_value
.native_flag
= max_value_int
.native_flag
;
2543 if (likely(value_range
.max_value
.native_flag
))
2544 value_range
.max_value
.val
.native
= max_value_int
.val
.native
;
2545 else value_range
.max_value
.val
.openssl
= BN_dup(max_value_int
.val
.openssl
);
2549 TTCN_error("Text decoder: An unknown/unsupported selection was received "
2550 "for an integer template.");
2554 boolean
INTEGER_template::is_present(boolean legacy
/* = FALSE */) const
2556 if (template_selection
==UNINITIALIZED_TEMPLATE
) return FALSE
;
2557 return !match_omit(legacy
);
2560 boolean
INTEGER_template::match_omit(boolean legacy
/* = FALSE */) const
2562 if (is_ifpresent
) return TRUE
;
2563 switch (template_selection
) {
2568 case COMPLEMENTED_LIST
:
2570 // legacy behavior: 'omit' can appear in the value/complement list
2571 for (unsigned int i
=0; i
<value_list
.n_values
; i
++)
2572 if (value_list
.list_value
[i
].match_omit())
2573 return template_selection
==VALUE_LIST
;
2574 return template_selection
==COMPLEMENTED_LIST
;
2576 // else fall through
2583 #ifndef TITAN_RUNTIME_2
2584 void INTEGER_template::check_restriction(template_res t_res
, const char* t_name
,
2585 boolean legacy
/* = FALSE */) const
2587 if (template_selection
==UNINITIALIZED_TEMPLATE
) return;
2588 switch ((t_name
&&(t_res
==TR_VALUE
))?TR_OMIT
:t_res
) {
2590 if (!is_ifpresent
&& template_selection
==SPECIFIC_VALUE
) return;
2593 if (!is_ifpresent
&& (template_selection
==OMIT_VALUE
||
2594 template_selection
==SPECIFIC_VALUE
)) return;
2597 if (!match_omit(legacy
)) return;
2602 TTCN_error("Restriction `%s' on template of type %s violated.",
2603 get_res_name(t_res
), t_name
? t_name
: "integer");