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 (!bound_flag
) return;
125 if (unlikely(!native_flag
)) BN_free(val
.openssl
);
128 void INTEGER::clean_up()
130 if (!bound_flag
) return;
131 if (unlikely(!native_flag
)) BN_free(val
.openssl
);
135 INTEGER
& INTEGER::operator=(int other_value
)
140 val
.native
= other_value
;
144 INTEGER
& INTEGER::operator=(const INTEGER
& other_value
)
146 if (this == &other_value
)
148 other_value
.must_bound("Assignment of an unbound integer value.");
151 native_flag
= other_value
.native_flag
;
152 if (likely(native_flag
)) val
.native
= other_value
.val
.native
;
153 else val
.openssl
= BN_dup(other_value
.val
.openssl
);
157 // A bit more specific than operator+().
158 INTEGER
& INTEGER::operator++()
160 must_bound("Unbound integer operand of unary increment operator.");
161 if (likely(native_flag
)) {
162 unsigned int result_u
= val
.native
+ 1;
163 int result
= val
.native
+ 1;
164 if (unlikely((static_cast<int>(result_u
) != result
) || (val
.native
> 0 && result
< 0))) {
165 BIGNUM
*val_openssl
= to_openssl(val
.native
);
166 BIGNUM
*one
= BN_new();
168 BN_add(val_openssl
, val_openssl
, one
);
171 val
.openssl
= val_openssl
;
176 BIGNUM
*one
= BN_new();
178 BN_add(val
.openssl
, val
.openssl
, one
);
184 // A bit more specific than operator-().
185 INTEGER
& INTEGER::operator--()
187 must_bound("Unbound integer operand of unary decrement operator.");
188 if (likely(native_flag
)) {
189 if (unlikely(val
.native
== INT_MIN
)) {
190 BIGNUM
*val_openssl
= to_openssl(val
.native
);
191 BIGNUM
*one
= BN_new();
193 BN_sub(val_openssl
, val_openssl
, one
);
196 val
.openssl
= val_openssl
;
201 BIGNUM
*one
= BN_new();
203 BN_sub(val
.openssl
, val
.openssl
, one
);
209 INTEGER
INTEGER::operator+() const
211 must_bound("Unbound integer operand of unary + operator.");
215 INTEGER
INTEGER::operator-() const
217 must_bound("Unbound integer operand of unary - operator (negation).");
218 if (likely(native_flag
)) {
219 if (unlikely(val
.native
== INT_MIN
)) {
220 BIGNUM
*result
= to_openssl(INT_MIN
);
221 BN_set_negative(result
, 0);
222 return INTEGER(result
);
224 return INTEGER(-val
.native
);
227 BIGNUM
*int_max_plus_one
= to_openssl(INT_MIN
);
228 BN_set_negative(int_max_plus_one
, 0);
229 int cmp
= BN_cmp(val
.openssl
, int_max_plus_one
);
230 BN_free(int_max_plus_one
);
231 if (unlikely(cmp
== 0)) {
232 return INTEGER(INT_MIN
);
234 BIGNUM
*result
= BN_dup(val
.openssl
);
235 BN_set_negative(result
, !BN_is_negative(result
));
236 return INTEGER(result
);
241 INTEGER
INTEGER::operator+(int other_value
) const
243 must_bound("Unbound left operand of integer addition.");
244 // Don't call out if slow. Implement this specific case right here.
245 return *this + INTEGER(other_value
);
248 INTEGER
INTEGER::operator+(const INTEGER
& other_value
) const
250 must_bound("Unbound left operand of integer addition.");
251 other_value
.must_bound("Unbound right operand of integer addition.");
252 // *this + other_value = *this add other_value
253 // *this + -other_value = *this sub other_value
254 // -*this + other_value = other_value sub *this
255 // -*this + -other_value = -(*this add other_value)
256 // Use only inline functions and BN_* directly. Call out for operator- in
258 boolean this_neg
= native_flag
? (val
.native
< 0)
259 : BN_is_negative(val
.openssl
);
260 boolean other_value_neg
= other_value
.native_flag
261 ? (other_value
.val
.native
< 0) : BN_is_negative(other_value
.val
.openssl
);
262 boolean result_neg
= this_neg
&& other_value_neg
;
263 if (!this_neg
&& other_value_neg
) return operator-(-other_value
);
264 if (this_neg
&& !other_value_neg
) return other_value
.operator-(-(*this));
265 if (likely(native_flag
)) {
266 if (likely(other_value
.native_flag
)) {
267 unsigned int result_u
= val
.native
+ other_value
.val
.native
;
268 int result
= val
.native
+ other_value
.val
.native
;
269 if ((static_cast<int>(result_u
) != result
) || (!result_neg
&&
270 result
< 0) || (result_neg
&& result
> 0)) {
271 // We can safely assume that the sum of two non-negative int values
272 // fit in an unsigned int. limits.h says:
273 // # define INT_MAX 2147483647
274 // # define UINT_MAX 4294967295
275 BIGNUM
*this_int
= to_openssl(val
.native
);
276 BIGNUM
*other_val_int
= to_openssl(other_value
.val
.native
);
277 BN_add(this_int
, this_int
, other_val_int
);
278 BN_free(other_val_int
);
279 return INTEGER(this_int
);
281 return INTEGER(result
);
284 // int (>= 0) + BIGNUM == BIGNUM.
285 BIGNUM
*this_int
= to_openssl(val
.native
);
286 BN_add(this_int
, this_int
, other_value
.val
.openssl
);
287 return INTEGER(this_int
);
290 // BIGNUM + int (>= 0) == BIGNUM.
291 BIGNUM
*result
= BN_new();
292 BIGNUM
*other_value_int
;
293 other_value_int
= other_value
.native_flag
294 ? to_openssl(other_value
.val
.native
) : other_value
.val
.openssl
;
295 BN_add(result
, val
.openssl
, other_value_int
);
296 if (likely(other_value
.native_flag
)) BN_free(other_value_int
);
297 return INTEGER(result
);
301 INTEGER
INTEGER::operator-(int other_value
) const
303 must_bound("Unbound left operand of integer subtraction.");
304 return *this - INTEGER(other_value
);
307 INTEGER
INTEGER::operator-(const INTEGER
& other_value
) const
309 must_bound("Unbound left operand of integer subtraction.");
310 other_value
.must_bound("Unbound right operand of integer subtraction.");
311 // *this - other_value = *this sub other_value
312 // -*this - other_value = -(*this add other_value)
313 // *this - -other_value = *this add other_value
314 // -*this - -other_value = -*this add other_value = other_value sub *this
315 boolean this_neg
= native_flag
? (val
.native
< 0)
316 : BN_is_negative(val
.openssl
);
317 boolean other_value_neg
= other_value
.native_flag
318 ? (other_value
.val
.native
< 0) : BN_is_negative(other_value
.val
.openssl
);
319 if (!this_neg
&& other_value_neg
) return operator+(-other_value
);
320 if (this_neg
&& !other_value_neg
) return -other_value
.operator+(-(*this));
321 if (likely(native_flag
)) {
322 if (likely(other_value
.native_flag
)) {
323 // Since both operands are non-negative the most negative result of a
324 // subtraction can be -INT_MAX and according to limits.h:
325 // # define INT_MIN (-INT_MAX - 1)
326 return INTEGER(val
.native
- other_value
.val
.native
);
328 BIGNUM
*this_int
= to_openssl(val
.native
);
329 BN_sub(this_int
, this_int
, other_value
.val
.openssl
);
330 // The result can be small enough to fit in int. Back conversion is a
331 // costly operation using strings all the time.
332 if (BN_num_bits(this_int
) <= (int)sizeof(int) * 8 - 1) {
333 char *result_str
= BN_bn2dec(this_int
);
334 RInt result
= string2RInt(result_str
);
335 OPENSSL_free(result_str
);
337 return INTEGER(result
);
339 return INTEGER(this_int
);
343 BIGNUM
*result
= BN_new();
344 BIGNUM
*other_value_int
= other_value
.native_flag
?
345 to_openssl(other_value
.val
.native
) : other_value
.val
.openssl
;
346 BN_sub(result
, val
.openssl
, other_value_int
);
347 if (other_value
.native_flag
) BN_free(other_value_int
);
348 if (BN_num_bits(result
) <= (int)sizeof(int) * 8 - 1) {
349 char *result_str
= BN_bn2dec(result
);
350 RInt result_int
= string2RInt(result_str
);
351 OPENSSL_free(result_str
);
353 return INTEGER(result_int
);
355 return INTEGER(result
);
360 INTEGER
INTEGER::operator*(int other_value
) const
362 must_bound("Unbound left operand of integer multiplication.");
363 return *this * INTEGER(other_value
);
366 INTEGER
INTEGER::operator*(const INTEGER
& other_value
) const
368 must_bound("Unbound left operand of integer multiplication.");
369 other_value
.must_bound("Unbound right operand of integer multiplication.");
370 if ((native_flag
&& val
.native
== 0) || (other_value
.native_flag
&&
371 other_value
.val
.native
== 0)) return INTEGER((int)0);
372 if (likely(native_flag
)) {
373 if (likely(other_value
.native_flag
)) {
375 if (likely(abs(val
.native
) < 32768 && abs(other_value
.val
.native
) < 32768)) {
376 return INTEGER(val
.native
* other_value
.val
.native
);
378 BIGNUM
*this_int
= to_openssl(val
.native
);
379 BIGNUM
*other_value_int
= to_openssl(other_value
.val
.native
);
380 BN_CTX
*ctx
= BN_CTX_new();
382 BN_mul(this_int
, this_int
, other_value_int
, ctx
);
384 BN_free(other_value_int
);
385 if (BN_num_bits(this_int
) < (int)sizeof(int) * 8) {
387 return INTEGER(val
.native
* other_value
.val
.native
);
389 return INTEGER(this_int
);
393 BIGNUM
*this_int
= to_openssl(val
.native
);
394 BN_CTX
*ctx
= BN_CTX_new();
396 BN_mul(this_int
, this_int
, other_value
.val
.openssl
, ctx
);
398 return INTEGER(this_int
);
401 BIGNUM
*result
= BN_new();
402 BIGNUM
*other_value_int
= NULL
;
403 BN_CTX
*ctx
= BN_CTX_new();
405 other_value_int
= other_value
.native_flag
406 ? to_openssl(other_value
.val
.native
) : other_value
.val
.openssl
;
407 BN_mul(result
, val
.openssl
, other_value_int
, ctx
);
409 if (likely(other_value
.native_flag
)) BN_free(other_value_int
);
410 return INTEGER(result
);
414 INTEGER
INTEGER::operator/(int other_value
) const
416 must_bound("Unbound left operand of integer division.");
417 if (other_value
== 0) TTCN_error("Integer division by zero.");
418 return *this / INTEGER(other_value
);
421 INTEGER
INTEGER::operator/(const INTEGER
& other_value
) const
423 must_bound("Unbound left operand of integer division.");
424 other_value
.must_bound("Unbound right operand of integer division.");
425 if (other_value
== 0) TTCN_error("Integer division by zero.");
426 if (native_flag
&& val
.native
== 0) return INTEGER((int)0);
427 if (likely(native_flag
)) {
428 if (likely(other_value
.native_flag
)) {
429 return INTEGER(val
.native
/ other_value
.val
.native
);
431 BIGNUM
*this_int
= to_openssl(val
.native
);
432 BN_CTX
*ctx
= BN_CTX_new();
434 BN_div(this_int
, NULL
, this_int
, other_value
.val
.openssl
, ctx
);
436 if (BN_num_bits(this_int
) <= (int)sizeof(int) * 8 - 1) {
437 char *result_str
= BN_bn2dec(this_int
);
438 RInt result
= string2RInt(result_str
);
439 OPENSSL_free(result_str
);
441 return INTEGER(result
);
443 return INTEGER(this_int
);
447 BIGNUM
*result
= BN_new();
448 BIGNUM
*other_value_int
= NULL
;
449 BN_CTX
*ctx
= BN_CTX_new();
451 other_value_int
= other_value
.native_flag
452 ? to_openssl(other_value
.val
.native
) : other_value
.val
.openssl
;
453 BN_div(result
, NULL
, val
.openssl
, other_value_int
, ctx
);
454 if (likely(other_value
.native_flag
)) BN_free(other_value_int
);
456 if (BN_num_bits(result
) <= (int)sizeof(int) * 8 - 1) {
457 char *result_str
= BN_bn2dec(result
);
458 RInt result_i
= string2RInt(result_str
);
459 OPENSSL_free(result_str
);
461 return INTEGER(result_i
);
463 return INTEGER(result
);
468 boolean
INTEGER::operator==(int other_value
) const
470 must_bound("Unbound left operand of integer comparison.");
471 if (likely(native_flag
)) {
472 return val
.native
== other_value
;
474 BIGNUM
*other_value_int
= to_openssl(other_value
);
475 int equal
= BN_cmp(val
.openssl
, other_value_int
);
476 BN_free(other_value_int
);
481 boolean
INTEGER::operator==(const INTEGER
& other_value
) const
483 must_bound("Unbound left operand of integer comparison.");
484 other_value
.must_bound("Unbound right operand of integer comparison.");
485 if (likely(native_flag
)) {
486 if (likely(other_value
.native_flag
)) {
487 return val
.native
== other_value
.val
.native
;
489 BIGNUM
*this_int
= to_openssl(val
.native
);
490 int equal
= BN_cmp(this_int
, other_value
.val
.openssl
);
495 if (likely(other_value
.native_flag
)) {
496 BIGNUM
*other_value_int
= to_openssl(other_value
.val
.native
);
497 int equal
= BN_cmp(val
.openssl
, other_value_int
);
498 BN_free(other_value_int
);
501 return BN_cmp(val
.openssl
, other_value
.val
.openssl
) == 0;
506 boolean
INTEGER::operator<(int other_value
) const
508 must_bound("Unbound left operand of integer comparison.");
509 return *this < INTEGER(other_value
);
512 boolean
INTEGER::operator<(const INTEGER
& other_value
) const
514 must_bound("Unbound left operand of integer comparison.");
515 other_value
.must_bound("Unbound right operand of integer comparison.");
516 if (likely(native_flag
)) {
517 if (likely(other_value
.native_flag
)) {
518 return val
.native
< other_value
.val
.native
;
520 BIGNUM
*this_int
= to_openssl(val
.native
);
521 int equal
= BN_cmp(this_int
, other_value
.val
.openssl
);
526 if (likely(other_value
.native_flag
)) {
527 BIGNUM
*other_value_int
= to_openssl(other_value
.val
.native
);
528 int equal
= BN_cmp(val
.openssl
, other_value_int
);
529 BN_free(other_value_int
);
532 return BN_cmp(val
.openssl
, other_value
.val
.openssl
) == -1;
537 boolean
INTEGER::operator>(int other_value
) const
539 must_bound("Unbound left operand of integer comparison.");
540 return *this > INTEGER(other_value
);
543 boolean
INTEGER::operator>(const INTEGER
& other_value
) const
545 // A simple call to operator< and operator== would be much simplier.
546 must_bound("Unbound left operand of integer comparison.");
547 other_value
.must_bound("Unbound right operand of integer comparison.");
548 if (likely(native_flag
)) {
549 if (likely(other_value
.native_flag
)) {
550 return val
.native
> other_value
.val
.native
;
552 BIGNUM
*this_int
= to_openssl(val
.native
);
553 int equal
= BN_cmp(this_int
, other_value
.val
.openssl
);
558 if (likely(other_value
.native_flag
)) {
559 BIGNUM
*other_value_int
= to_openssl(other_value
.val
.native
);
560 int equal
= BN_cmp(val
.openssl
, other_value_int
);
561 BN_free(other_value_int
);
564 return BN_cmp(val
.openssl
, other_value
.val
.openssl
) == 1;
569 INTEGER::operator int() const
571 must_bound("Using the value of an unbound integer variable.");
572 if (unlikely(!native_flag
))
573 TTCN_error("Invalid conversion of a large integer value");
577 // To avoid ambiguity we have a separate function to convert our INTEGER
578 // object to long long.
579 long long int INTEGER::get_long_long_val() const
581 must_bound("Using the value of an unbound integer variable.");
582 if (likely(native_flag
)) return val
.native
;
583 size_t slot_size
= sizeof(BN_ULONG
);
584 bool is_negative
= BN_is_negative(val
.openssl
);
585 long long int ret_val
= 0;
586 if (unlikely(val
.openssl
->top
== 0)) return 0;
587 // It feels so bad accessing a BIGNUM directly, but faster than string
589 else if (likely(val
.openssl
->top
== 1))
590 return !is_negative
? val
.openssl
->d
[0] : -val
.openssl
->d
[0];
591 ret_val
= val
.openssl
->d
[val
.openssl
->top
- 1];
592 // From now, shift by 8.
593 for (int i
= val
.openssl
->top
- 2; i
>= 0; i
--) {
594 for (int j
= slot_size
- 1; j
>= 0; j
--) {
595 unsigned char tmp
= (val
.openssl
->d
[i
] >> 8 * j
) & 0xff;
600 return !is_negative
? ret_val
: -ret_val
;
603 void INTEGER::set_long_long_val(long long int other_value
)
607 // Seems to be a native. It's very strange if someone calls this with a
608 // small number. A simple assignment should be used for such values.
609 if (unlikely((RInt
)other_value
== other_value
)) {
611 val
.native
= other_value
;
615 val
.openssl
= BN_new();
617 BN_zero(val
.openssl
);
618 bool is_negative
= other_value
< 0;
619 unsigned long long int tmp
= !is_negative
? other_value
: -other_value
;
620 for (int i
= sizeof(long long int) - 1; i
>= 0; i
--) {
621 BN_add_word(val
.openssl
, (tmp
>> 8 * i
) & 0xff);
622 if (i
) BN_lshift(val
.openssl
, val
.openssl
, 8);
624 BN_set_negative(val
.openssl
, is_negative
? 1 : 0);
627 void INTEGER::log() const
629 if (likely(bound_flag
)) {
630 if (likely(native_flag
)) {
631 TTCN_Logger::log_event("%d", val
.native
);
633 char *tmp
= BN_bn2dec(val
.openssl
);
634 TTCN_Logger::log_event("%s", tmp
);
638 TTCN_Logger::log_event_unbound();
642 void INTEGER::set_param(Module_Param
& param
)
644 param
.basic_check(Module_Param::BC_VALUE
, "integer value");
645 Module_Param_Ptr mp
= ¶m
;
646 if (param
.get_type() == Module_Param::MP_Reference
) {
647 mp
= param
.get_referenced_param();
649 switch (mp
->get_type()) {
650 case Module_Param::MP_Integer
: {
653 const int_val_t
* const int_val
= mp
->get_integer();
654 native_flag
= int_val
->is_native();
655 if (likely(native_flag
)){
656 val
.native
= int_val
->get_val();
658 val
.openssl
= BN_dup(int_val
->get_val_openssl());
661 case Module_Param::MP_Expression
:
662 switch (mp
->get_expr_type()) {
663 case Module_Param::EXPR_NEGATE
: {
665 operand
.set_param(*mp
->get_operand1());
668 case Module_Param::EXPR_ADD
: {
669 INTEGER operand1
, operand2
;
670 operand1
.set_param(*mp
->get_operand1());
671 operand2
.set_param(*mp
->get_operand2());
672 *this = operand1
+ operand2
;
674 case Module_Param::EXPR_SUBTRACT
: {
675 INTEGER operand1
, operand2
;
676 operand1
.set_param(*mp
->get_operand1());
677 operand2
.set_param(*mp
->get_operand2());
678 *this = operand1
- operand2
;
680 case Module_Param::EXPR_MULTIPLY
: {
681 INTEGER operand1
, operand2
;
682 operand1
.set_param(*mp
->get_operand1());
683 operand2
.set_param(*mp
->get_operand2());
684 *this = operand1
* operand2
;
686 case Module_Param::EXPR_DIVIDE
: {
687 INTEGER operand1
, operand2
;
688 operand1
.set_param(*mp
->get_operand1());
689 operand2
.set_param(*mp
->get_operand2());
691 param
.error("Integer division by zero.");
693 *this = operand1
/ operand2
;
696 param
.expr_type_error("an integer");
701 param
.type_error("integer value");
706 Module_Param
* INTEGER::get_param(Module_Param_Name
& /* param_name */) const
709 return new Module_Param_Unbound();
712 return new Module_Param_Integer(new int_val_t(val
.native
));
714 return new Module_Param_Integer(new int_val_t(BN_dup(val
.openssl
)));
717 void INTEGER::encode_text(Text_Buf
& text_buf
) const
719 must_bound("Text encoder: Encoding an unbound integer value.");
720 if (likely(native_flag
)) {
721 text_buf
.push_int(val
.native
);
723 int_val_t
*tmp
= new int_val_t(BN_dup(val
.openssl
));
724 text_buf
.push_int(*tmp
);
729 void INTEGER::decode_text(Text_Buf
& text_buf
)
733 int_val_t
tmp(text_buf
.pull_int());
734 if (likely(tmp
.native_flag
)) {
736 val
.native
= tmp
.get_val();
739 val
.openssl
= BN_dup(tmp
.get_val_openssl());
743 void INTEGER::encode(const TTCN_Typedescriptor_t
& p_td
, TTCN_Buffer
& p_buf
,
744 TTCN_EncDec::coding_t p_coding
, ...) const
747 va_start(pvar
, p_coding
);
749 case TTCN_EncDec::CT_BER
: {
750 TTCN_EncDec_ErrorContext
ec("While BER-encoding type '%s': ", p_td
.name
);
751 unsigned BER_coding
=va_arg(pvar
, unsigned);
752 BER_encode_chk_coding(BER_coding
);
753 ASN_BER_TLV_t
*tlv
=BER_encode_TLV(p_td
, BER_coding
);
754 tlv
->put_in_buffer(p_buf
);
755 ASN_BER_TLV_t::destruct(tlv
);
757 case TTCN_EncDec::CT_RAW
: {
758 TTCN_EncDec_ErrorContext
ec("While RAW-encoding type '%s': ", p_td
.name
);
760 TTCN_EncDec_ErrorContext::error_internal
761 ("No RAW descriptor available for type '%s'.", p_td
.name
);
765 RAW_enc_tree
root(TRUE
,NULL
,&rp
,1,p_td
.raw
);
766 RAW_encode(p_td
, root
);
767 root
.put_to_buf(p_buf
);
769 case TTCN_EncDec::CT_TEXT
: {
770 TTCN_EncDec_ErrorContext
ec("While TEXT-encoding type '%s': ", p_td
.name
);
772 TTCN_EncDec_ErrorContext::error_internal
773 ("No TEXT descriptor available for type '%s'.", p_td
.name
);
774 TEXT_encode(p_td
,p_buf
);
776 case TTCN_EncDec::CT_XER
: {
777 TTCN_EncDec_ErrorContext
ec("While XER-encoding type '%s': ", p_td
.name
);
778 unsigned XER_coding
=va_arg(pvar
, unsigned);
779 XER_encode(*p_td
.xer
, p_buf
, XER_coding
, 0, 0);
781 case TTCN_EncDec::CT_JSON
: {
782 TTCN_EncDec_ErrorContext
ec("While JSON-encoding type '%s': ", p_td
.name
);
784 TTCN_EncDec_ErrorContext::error_internal
785 ("No JSON descriptor available for type '%s'.", p_td
.name
);
786 JSON_Tokenizer
tok(va_arg(pvar
, int) != 0);
787 JSON_encode(p_td
, tok
);
788 p_buf
.put_s(tok
.get_buffer_length(), (const unsigned char*)tok
.get_buffer());
791 TTCN_error("Unknown coding method requested to encode type '%s'",
797 void INTEGER::decode(const TTCN_Typedescriptor_t
& p_td
, TTCN_Buffer
& p_buf
,
798 TTCN_EncDec::coding_t p_coding
, ...)
801 va_start(pvar
, p_coding
);
803 case TTCN_EncDec::CT_BER
: {
804 TTCN_EncDec_ErrorContext
ec("While BER-decoding type '%s': ", p_td
.name
);
805 unsigned L_form
=va_arg(pvar
, unsigned);
807 BER_decode_str2TLV(p_buf
, tlv
, L_form
);
808 BER_decode_TLV(p_td
, tlv
, L_form
);
809 if(tlv
.isComplete
) p_buf
.increase_pos(tlv
.get_len());
811 case TTCN_EncDec::CT_RAW
: {
812 TTCN_EncDec_ErrorContext
ec("While RAW-decoding type '%s': ", p_td
.name
);
814 TTCN_EncDec_ErrorContext::error_internal
815 ("No RAW descriptor available for type '%s'.", p_td
.name
);
817 switch(p_td
.raw
->top_bit_order
){
825 if(RAW_decode(p_td
, p_buf
, p_buf
.get_len()*8, order
)<0)
826 ec
.error(TTCN_EncDec::ET_INCOMPL_MSG
,
827 "Can not decode type '%s', because invalid or incomplete"
828 " message was received"
831 case TTCN_EncDec::CT_TEXT
: {
832 Limit_Token_List limit
;
833 TTCN_EncDec_ErrorContext
ec("While TEXT-decoding type '%s': ", p_td
.name
);
835 TTCN_EncDec_ErrorContext::error_internal
836 ("No TEXT descriptor available for type '%s'.", p_td
.name
);
837 const unsigned char *b
=p_buf
.get_data();
838 if(b
[p_buf
.get_len()-1]!='\0'){
839 p_buf
.set_pos(p_buf
.get_len());
840 p_buf
.put_zero(8,ORDER_LSB
);
843 if(TEXT_decode(p_td
,p_buf
,limit
)<0)
844 ec
.error(TTCN_EncDec::ET_INCOMPL_MSG
,
845 "Can not decode type '%s', because invalid or incomplete"
846 " message was received"
849 case TTCN_EncDec::CT_XER
: {
850 TTCN_EncDec_ErrorContext
ec("While XER-decoding type '%s': ", p_td
.name
);
851 unsigned XER_coding
=va_arg(pvar
, unsigned);
852 XmlReaderWrap
reader(p_buf
);
853 for (int success
= reader
.Read(); success
==1; success
=reader
.Read()) {
854 int type
= reader
.NodeType();
855 if (type
==XML_READER_TYPE_ELEMENT
)
858 XER_decode(*p_td
.xer
, reader
, XER_coding
, XER_NONE
, 0);
859 size_t bytes
= reader
.ByteConsumed();
860 p_buf
.set_pos(bytes
);
862 case TTCN_EncDec::CT_JSON
: {
863 TTCN_EncDec_ErrorContext
ec("While JSON-decoding type '%s': ", p_td
.name
);
865 TTCN_EncDec_ErrorContext::error_internal
866 ("No JSON descriptor available for type '%s'.", p_td
.name
);
867 JSON_Tokenizer
tok((const char*)p_buf
.get_data(), p_buf
.get_len());
868 if(JSON_decode(p_td
, tok
, false)<0)
869 ec
.error(TTCN_EncDec::ET_INCOMPL_MSG
,
870 "Can not decode type '%s', because invalid or incomplete"
871 " message was received"
873 p_buf
.set_pos(tok
.get_buf_pos());
876 TTCN_error("Unknown coding method requested to decode type '%s'",
882 ASN_BER_TLV_t
*INTEGER::BER_encode_TLV(const TTCN_Typedescriptor_t
& p_td
,
883 unsigned p_coding
) const
886 ASN_BER_TLV_t
*new_tlv
= BER_encode_chk_bound(is_bound());
889 new_tlv
= BER_encode_TLV_INTEGER(p_coding
, val
.native
);
892 int_val_t
*tmp
= new int_val_t(BN_dup(val
.openssl
));
893 new_tlv
= BER_encode_TLV_INTEGER(p_coding
, *tmp
);
897 new_tlv
= ASN_BER_V2TLV(new_tlv
, p_td
, p_coding
);
901 boolean
INTEGER::BER_decode_TLV(const TTCN_Typedescriptor_t
& p_td
,
902 const ASN_BER_TLV_t
& p_tlv
,
908 ASN_BER_TLV_t stripped_tlv
;
909 BER_decode_strip_tags(*p_td
.ber
, p_tlv
, L_form
, stripped_tlv
);
910 TTCN_EncDec_ErrorContext
ec("While decoding INTEGER type: ");
912 boolean ret_val
= BER_decode_TLV_INTEGER(stripped_tlv
, L_form
, tmp
);
913 if (tmp
.is_native()) {
915 val
.native
= tmp
.get_val();
918 val
.openssl
= BN_dup(tmp
.get_val_openssl());
920 if (ret_val
) bound_flag
= TRUE
;
924 int INTEGER::TEXT_decode(const TTCN_Typedescriptor_t
& p_td
,
925 TTCN_Buffer
& buff
, Limit_Token_List
& limit
, boolean no_err
, boolean
/*first_call*/)
927 int decoded_length
= 0;
929 if (p_td
.text
->begin_decode
) {
931 if ((tl
= p_td
.text
->begin_decode
->match_begin(buff
)) < 0) {
932 if (no_err
) return -1;
933 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_TOKEN_ERR
,
934 "The specified token '%s' not found for '%s': ",
935 (const char*)*(p_td
.text
->begin_decode
), p_td
.name
);
938 decoded_length
+= tl
;
939 buff
.increase_pos(tl
);
941 if (buff
.get_read_len() <= 1 && no_err
) return -TTCN_EncDec::ET_LEN_ERR
;
942 if (p_td
.text
->select_token
) {
944 if ((tl
= p_td
.text
->select_token
->match_begin(buff
)) < 0) {
945 if (no_err
) return -1;
949 } else if ( p_td
.text
->val
.parameters
950 && p_td
.text
->val
.parameters
->decoding_params
.min_length
!= -1) {
951 str_len
= p_td
.text
->val
.parameters
->decoding_params
.min_length
;
952 } else if (p_td
.text
->end_decode
) {
954 if ((tl
= p_td
.text
->end_decode
->match_first(buff
)) < 0) {
955 if (no_err
) return -1;
959 } else if (limit
.has_token()) {
961 if ((tl
= limit
.match(buff
)) < 0) {
962 if (no_err
) return -1;
968 if ((tl
= integer_value_match
.match_begin(buff
)) < 0) {
969 if (no_err
) return -1;
977 char *atm
= (char*)Malloc(str_len
+ 1); // sizeof(char) == 1 by definition
978 const char *b
= (const char*)buff
.get_read_data();
979 memcpy(atm
, b
, str_len
);
984 int neg
= *atm
== 0x2d ? 1 : 0;
986 for (offs
= neg
; *(atm
+ offs
) == 0x30; offs
++) ; // E.g. 0, -0, 00001234, -00001234.
987 if (neg
&& offs
> 1) *(atm
+ offs
- 1) = *atm
; // E.g. -00001234 -> -000-1234.
990 for(; atm
[offs
] == 0x20; offs
++) ;
993 if (0 == strlen(atm
+ offs
) || 0 == from_string(atm
+offs
)) {
999 buff
.increase_pos(str_len
);
1000 decoded_length
+= str_len
;
1005 if (no_err
) return -1;
1006 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_TOKEN_ERR
,
1007 "Can not decode a valid integer for '%s': ", p_td
.name
);
1009 if (p_td
.text
->end_decode
) {
1011 if ((tl
= p_td
.text
->end_decode
->match_begin(buff
)) < 0) {
1012 if (no_err
) return -1;
1013 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_TOKEN_ERR
,
1014 "The specified token '%s' not found for '%s': ",
1015 (const char*)*(p_td
.text
->end_decode
), p_td
.name
);
1018 decoded_length
+= tl
;
1019 buff
.increase_pos(tl
);
1022 return decoded_length
;
1025 int INTEGER::TEXT_encode(const TTCN_Typedescriptor_t
& p_td
,
1026 TTCN_Buffer
& buff
) const
1028 int encoded_length
= 0;
1029 if (p_td
.text
->begin_encode
) {
1030 buff
.put_cs(*p_td
.text
->begin_encode
);
1031 encoded_length
+= p_td
.text
->begin_encode
->lengthof();
1034 TTCN_EncDec_ErrorContext::error
1035 (TTCN_EncDec::ET_UNBOUND
,"Encoding an unbound value.");
1036 if (p_td
.text
->end_encode
) {
1037 buff
.put_cs(*p_td
.text
->end_encode
);
1038 encoded_length
+=p_td
.text
->end_encode
->lengthof();
1040 return encoded_length
;
1044 if (native_flag
) tmp_str
= mprintf("%d", val
.native
);
1045 else tmp_str
= BN_bn2dec(val
.openssl
);
1046 CHARSTRING
ch(tmp_str
);
1047 if (native_flag
) Free(tmp_str
);
1048 else OPENSSL_free(tmp_str
);
1049 if (p_td
.text
->val
.parameters
== NULL
) {
1051 encoded_length
+= ch
.lengthof();
1053 TTCN_TEXTdescriptor_values params
= p_td
.text
->val
.parameters
1055 if (params
.min_length
< 0) {
1057 encoded_length
+= ch
.lengthof();
1059 unsigned char *p
= NULL
;
1061 size_t len
= params
.min_length
+ 1;
1062 buff
.get_end(p
, len
);
1063 if (params
.leading_zero
) {
1065 a
= snprintf((char*)p
, len
, "%0*d", params
.min_length
, val
.native
);
1067 int chlen
= ch
.lengthof(), pad
= 0;
1068 int neg
= native_flag
? (val
.native
< 0) : BN_is_negative(val
.openssl
);
1069 if (params
.min_length
> chlen
)
1070 pad
= params
.min_length
- chlen
+ neg
;
1073 memset(p
+ neg
, 0x30, pad
);
1074 for (int i
= 0; i
< chlen
- neg
; i
++)
1075 p
[i
+ pad
] = ch
[i
+ neg
].get_char();
1076 a
+= pad
+ chlen
- neg
;
1079 a
= snprintf((char*)p
, len
, "%*s", p_td
.text
->val
.parameters
->
1080 coding_params
.min_length
, (const char*)ch
);
1082 buff
.increase_length(a
);
1083 encoded_length
+= a
;
1086 if (p_td
.text
->end_encode
) {
1087 buff
.put_cs(*p_td
.text
->end_encode
);
1088 encoded_length
+= p_td
.text
->end_encode
->lengthof();
1090 return encoded_length
;
1093 unsigned char INTX_MASKS
[] = { 0 /*dummy*/, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF };
1095 int INTEGER::RAW_encode(const TTCN_Typedescriptor_t
& p_td
, RAW_enc_tree
& myleaf
) const
1097 if (!native_flag
) return RAW_encode_openssl(p_td
, myleaf
);
1099 int length
; // total length, in bytes
1100 int val_bits
= 0, len_bits
= 0; // only for IntX
1101 int value
= val
.native
;
1102 boolean neg_sgbit
= (value
< 0) && (p_td
.raw
->comp
== SG_SG_BIT
);
1104 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND
,
1105 "Encoding an unbound value.");
1109 if (value
!= 0 && value
== -value
) {
1110 // value == -INT_MAX-1 a.k.a. INT_MIN a.k.a. 0x8000....
1111 INTEGER
big_value(to_openssl(val
.native
)); // too big for native
1112 return big_value
.RAW_encode_openssl(p_td
, myleaf
);
1114 if ((value
< 0) && (p_td
.raw
->comp
== SG_NO
)) {
1115 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_SIGN_ERR
,
1116 "Unsigned encoding of a negative number: %s", p_td
.name
);
1119 if (neg_sgbit
) value
= -value
;
1120 //myleaf.ext_bit=EXT_BIT_NO;
1121 if (myleaf
.must_free
) Free(myleaf
.body
.leaf
.data_ptr
);
1122 if (p_td
.raw
->fieldlength
== RAW_INTX
) { // IntX (variable length)
1123 val_bits
= (p_td
.raw
->comp
!= SG_NO
); // bits needed to store the value
1125 if (v2
< 0 && p_td
.raw
->comp
== SG_2COMPL
) {
1133 len_bits
= 1 + val_bits
/ 8; // bits needed to store the length
1134 if (val_bits
% 8 + len_bits
% 8 > 8) {
1135 // the remainder of the value bits and the length bits do not fit into
1136 // an octet => an extra octet is needed and the length must be increased
1139 length
= (len_bits
+ val_bits
+ 7) / 8;
1140 if (len_bits
% 8 == 0 && val_bits
% 8 != 0) {
1141 // special case: the value can be stored on 8k - 1 octets plus the partial octet
1142 // - len_bits = 8k is not enough, since there's no partial octet in that case
1143 // and the length would then be followed by 8k octets (and it only indicates
1144 // 8k - 1 further octets)
1145 // - len_bits = 8k + 1 is too much, since there are only 8k - 1 octets
1146 // following the partial octet (and 8k are indicated)
1147 // solution: len_bits = 8k + 1 and insert an extra empty octet
1152 else { // not IntX, use the field length
1153 length
= (p_td
.raw
->fieldlength
+ 7) / 8;
1154 if (min_bits(value
) > p_td
.raw
->fieldlength
) {
1155 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_LEN_ERR
,
1156 "There are insufficient bits to encode '%s' : ", p_td
.name
);
1157 value
= 0; // substitute with zero
1160 if (length
> RAW_INT_ENC_LENGTH
) { // does not fit in the small buffer
1161 myleaf
.body
.leaf
.data_ptr
= bc
= (unsigned char*)Malloc(length
* sizeof(*bc
));
1162 myleaf
.must_free
= TRUE
;
1163 myleaf
.data_ptr_used
= TRUE
;
1165 else bc
= myleaf
.body
.leaf
.data_array
;
1166 if (p_td
.raw
->fieldlength
== RAW_INTX
) {
1168 // treat the empty space between the value and the length as if it was part
1169 // of the value, too
1170 val_bits
= length
* 8 - len_bits
;
1171 // first, encode the value
1173 bc
[i
] = value
& INTX_MASKS
[val_bits
> 8 ? 8 : val_bits
];
1178 while (val_bits
> 0);
1180 // the sign bit is the first bit after the length
1181 unsigned char mask
= 0x80 >> len_bits
% 8;
1184 // second, encode the length (ignore the last zero)
1186 if (val_bits
!= 0) {
1187 // the remainder of the length is in the same octet as the remainder of the
1188 // value => step back onto it
1192 // the remainder of the length is in a separate octet
1195 // insert the length's partial octet
1196 unsigned char mask
= 0x80;
1197 for (int j
= 0; j
< len_bits
% 8; ++j
) {
1201 if (len_bits
% 8 > 0 || val_bits
!= 0) {
1202 // there was a partial octet => step onto the first full octet
1205 // insert the length's full octets
1206 while (len_bits
>= 8) {
1207 // octets containing only ones in the length
1212 myleaf
.length
= length
* 8;
1215 for (int a
= 0; a
< length
; a
++) {
1216 bc
[a
] = value
& 0xFF;
1220 unsigned char mask
= 0x01 << (p_td
.raw
->fieldlength
- 1) % 8;
1221 bc
[length
- 1] |= mask
;
1223 myleaf
.length
= p_td
.raw
->fieldlength
;
1225 return myleaf
.length
;
1228 int INTEGER::RAW_encode_openssl(const TTCN_Typedescriptor_t
& p_td
,
1229 RAW_enc_tree
& myleaf
) const
1231 unsigned char *bc
= NULL
;
1232 int length
; // total length, in bytes
1233 int val_bits
= 0, len_bits
= 0; // only for IntX
1234 BIGNUM
*D
= BN_new();
1235 BN_copy(D
, val
.openssl
);
1236 boolean neg_sgbit
= (D
->neg
) && (p_td
.raw
->comp
== SG_SG_BIT
);
1238 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND
,
1239 "Encoding an unbound value.");
1243 if ((D
->neg
) && (p_td
.raw
->comp
== SG_NO
)) {
1244 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_SIGN_ERR
,
1245 "Unsigned encoding of a negative number: %s", p_td
.name
);
1246 BN_set_negative(D
, 0);
1249 // `if (neg_sgbit) tmp->neg = tmp->neg == 0;' is not needed, because the
1250 // sign is stored separately from the number. Default encoding of negative
1251 // values in 2's complement form.
1252 if (myleaf
.must_free
) Free(myleaf
.body
.leaf
.data_ptr
);
1253 if (p_td
.raw
->fieldlength
== RAW_INTX
) {
1254 val_bits
= BN_num_bits(D
) + (p_td
.raw
->comp
!= SG_NO
); // bits needed to store the value
1255 len_bits
= 1 + val_bits
/ 8; // bits needed to store the length
1256 if (val_bits
% 8 + len_bits
% 8 > 8) {
1257 // the remainder of the value bits and the length bits do not fit into
1258 // an octet => an extra octet is needed and the length must be increased
1261 length
= (len_bits
+ val_bits
+ 7) / 8;
1262 if (len_bits
% 8 == 0 && val_bits
% 8 != 0) {
1263 // special case: the value can be stored on 8k - 1 octets plus the partial octet
1264 // - len_bits = 8k is not enough, since there's no partial octet in that case
1265 // and the length would then be followed by 8k octets (and it only indicates
1266 // 8k - 1 further octets)
1267 // - len_bits = 8k + 1 is too much, since there are only 8k - 1 octets
1268 // following the partial octet (and 8k are indicated)
1269 // solution: len_bits = 8k + 1 and insert an extra empty octet
1275 length
= (p_td
.raw
->fieldlength
+ 7) / 8;
1276 if (min_bits(D
) > p_td
.raw
->fieldlength
) {
1277 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_LEN_ERR
,
1278 "There are insufficient bits to encode '%s': ", p_td
.name
);
1279 // `tmp = -((-tmp) & BitMaskTable[min_bits(tmp)]);' doesn't make any sense
1280 // at all for negative values. Just simply clear the value.
1285 if (length
> RAW_INT_ENC_LENGTH
) {
1286 myleaf
.body
.leaf
.data_ptr
= bc
=
1287 (unsigned char *)Malloc(length
* sizeof(*bc
));
1288 myleaf
.must_free
= TRUE
;
1289 myleaf
.data_ptr_used
= TRUE
;
1291 bc
= myleaf
.body
.leaf
.data_array
;
1293 boolean twos_compl
= (D
->neg
) && !neg_sgbit
;
1294 // Conversion to 2's complement.
1296 BN_set_negative(D
, 0);
1297 for (int a
= 0; a
< D
->dmax
; a
++) D
->d
[a
] = ~D
->d
[a
];
1300 if (p_td
.raw
->fieldlength
== RAW_INTX
) {
1302 // treat the empty space between the value and the length as if it was part
1303 // of the value, too
1304 val_bits
= length
* 8 - len_bits
;
1305 // first, encode the value
1307 bc
[i
] = (D
->top
? D
->d
[0] : (twos_compl
? 0xFF : 0)) & INTX_MASKS
[val_bits
> 8 ? 8 : val_bits
];
1312 while (val_bits
> 0);
1314 // the sign bit is the first bit after the length
1315 unsigned char mask
= 0x80 >> len_bits
% 8;
1318 // second, encode the length (ignore the last zero)
1320 if (val_bits
!= 0) {
1321 // the remainder of the length is in the same octet as the remainder of the
1322 // value => step back onto it
1326 // the remainder of the length is in a separate octet
1329 // insert the length's partial octet
1330 unsigned char mask
= 0x80;
1331 for (int j
= 0; j
< len_bits
% 8; ++j
) {
1335 if (len_bits
% 8 > 0 || val_bits
!= 0) {
1336 // there was a partial octet => step onto the first full octet
1339 // insert the length's full octets
1340 while (len_bits
>= 8) {
1341 // octets containing only ones in the length
1346 myleaf
.length
= length
* 8;
1349 int num_bytes
= BN_num_bytes(D
);
1350 for (int a
= 0; a
< length
; a
++) {
1351 if (twos_compl
&& num_bytes
- 1 < a
) bc
[a
] = 0xff;
1352 else bc
[a
] = (D
->top
? D
->d
[0] : 0) & 0xff;
1356 unsigned char mask
= 0x01 << (p_td
.raw
->fieldlength
- 1) % 8;
1357 bc
[length
- 1] |= mask
;
1360 myleaf
.length
= p_td
.raw
->fieldlength
;
1362 return myleaf
.length
;
1365 int INTEGER::RAW_decode(const TTCN_Typedescriptor_t
& p_td
, TTCN_Buffer
& buff
,
1366 int limit
, raw_order_t top_bit_ord
, boolean no_err
, int /*sel_field*/,
1367 boolean
/*first_call*/)
1370 int prepaddlength
= buff
.increase_pos_padd(p_td
.raw
->prepadding
);
1371 limit
-= prepaddlength
;
1373 boolean orders
= FALSE
;
1374 if (p_td
.raw
->bitorderinoctet
== ORDER_MSB
) orders
= TRUE
;
1375 if (p_td
.raw
->bitorderinfield
== ORDER_MSB
) orders
= !orders
;
1376 cp
.bitorder
= orders
? ORDER_MSB
: ORDER_LSB
;
1378 if (p_td
.raw
->byteorder
== ORDER_MSB
) orders
= TRUE
;
1379 if (p_td
.raw
->bitorderinfield
== ORDER_MSB
) orders
= !orders
;
1380 cp
.byteorder
= orders
? ORDER_MSB
: ORDER_LSB
;
1381 cp
.fieldorder
= p_td
.raw
->fieldorder
;
1382 cp
.hexorder
= ORDER_LSB
;
1383 int decode_length
= 0;
1384 int len_bits
= 0; // only for IntX (amount of bits used to store the length)
1385 unsigned char len_data
= 0; // only for IntX (an octet used to store the length)
1386 int partial_octet_bits
= 0; // only for IntX (amount of value bits in the partial octet)
1387 if (p_td
.raw
->fieldlength
== RAW_INTX
) {
1388 // extract the length
1390 // check if at least 8 bits are available in the buffer
1393 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_LEN_ERR
,
1394 "There are not enough bits in the buffer to decode the length of IntX "
1395 "type %s (needed: %d, found: %d).", p_td
.name
, len_bits
+ 8,
1398 return -TTCN_EncDec::ET_LEN_ERR
;
1403 int nof_unread_bits
= buff
.unread_len_bit();
1404 if (nof_unread_bits
< 8) {
1406 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_INCOMPL_MSG
,
1407 "There are not enough bits in the buffer to decode the length of IntX "
1408 "type %s (needed: %d, found: %d).", p_td
.name
, len_bits
+ 8,
1409 len_bits
+ nof_unread_bits
);
1411 return -TTCN_EncDec::ET_INCOMPL_MSG
;
1414 // extract the next length octet (or partial length octet)
1415 buff
.get_b(8, &len_data
, cp
, top_bit_ord
);
1416 unsigned char mask
= 0x80;
1419 if (len_data
& mask
) {
1423 // the first zero signals the end of the length
1424 // the rest of the bits in the octet are part of the value
1425 partial_octet_bits
= (8 - len_bits
% 8) % 8;
1427 // decode_length only stores the amount of bits in full octets needed
1428 // by the value, the bits in the partial octet are stored by len_data
1429 decode_length
= 8 * (len_bits
- 1);
1433 while (len_bits
% 8 != 0);
1435 while (decode_length
== 0 && partial_octet_bits
== 0);
1438 // not IntX, use the static field length
1439 decode_length
= p_td
.raw
->fieldlength
;
1441 if (decode_length
> limit
) {
1443 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_LEN_ERR
,
1444 "There are not enough bits in the buffer to decode%s type %s (needed: %d, "
1445 "found: %d).", p_td
.raw
->fieldlength
== RAW_INTX
? " the value of IntX" : "",
1446 p_td
.name
, decode_length
, limit
);
1448 if (no_err
|| p_td
.raw
->fieldlength
== RAW_INTX
) {
1449 return -TTCN_EncDec::ET_LEN_ERR
;
1451 decode_length
= limit
;
1453 int nof_unread_bits
= buff
.unread_len_bit();
1454 if (decode_length
> nof_unread_bits
) {
1456 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_INCOMPL_MSG
,
1457 "There are not enough bits in the buffer to decode%s type %s (needed: %d, "
1458 "found: %d).", p_td
.raw
->fieldlength
== RAW_INTX
? " the value of IntX" : "",
1459 p_td
.name
, decode_length
, nof_unread_bits
);
1461 if (no_err
|| p_td
.raw
->fieldlength
== RAW_INTX
) {
1462 return -TTCN_EncDec::ET_INCOMPL_MSG
;
1464 decode_length
= nof_unread_bits
;
1467 if (decode_length
< 0) return -1;
1468 else if (decode_length
== 0 && partial_octet_bits
== 0) {
1475 unsigned char *data
= (unsigned char *) Malloc(
1476 (decode_length
+ partial_octet_bits
+ 7) / 8);
1477 buff
.get_b((size_t) decode_length
, data
, cp
, top_bit_ord
);
1478 if (partial_octet_bits
!= 0) {
1479 // in case there are value bits in the last length octet (only for IntX),
1480 // these need to be appended to the extracted data
1481 data
[decode_length
/ 8] = len_data
;
1482 decode_length
+= partial_octet_bits
;
1484 int end_pos
= decode_length
;
1485 int idx
= (end_pos
- 1) / 8;
1486 boolean negativ_num
= FALSE
;
1487 switch (p_td
.raw
->comp
) {
1489 if (data
[idx
] >> ((end_pos
- 1) % 8) & 0x01) {
1497 negativ_num
= (data
[idx
] >> ((end_pos
- 1) % 8)) & 0x01;
1505 tmp
|= data
[0] & BitMaskTable
[end_pos
];
1508 idx
= (end_pos
- 1) / 8;
1509 tmp
<<= (end_pos
- 1) % 8 + 1;
1510 tmp
|= data
[idx
--] & BitMaskTable
[(end_pos
- 1) % 8 + 1];
1511 if (decode_length
> (RInt
) sizeof(RInt
) * 8 - 1) {
1512 BIGNUM
*D
= BN_new();
1513 BN_set_word(D
, tmp
);
1514 int pad
= tmp
== 0 ? 1 : 0;
1515 for (; idx
>= 0; idx
--) {
1516 if (pad
&& data
[idx
] != 0) {
1517 BN_set_word(D
, data
[idx
] & 0xff);
1523 BN_add_word(D
, data
[idx
] & 0xff);
1526 BIGNUM
*D_tmp
= BN_new();
1527 BN_set_bit(D_tmp
, BN_num_bits(D
));
1528 BN_sub(D
, D
, D_tmp
);
1531 else if (negativ_num
) {
1532 BN_set_negative(D
, 1);
1534 // Back to native. "BN_num_bits(D) + BN_is_negative(D) >
1535 // (RInt)sizeof(RInt) * 8 - !BN_is_negative(D)" was an over-complicated
1537 if (BN_num_bits(D
) > (RInt
) sizeof(RInt
) * 8 - 1) {
1538 native_flag
= FALSE
;
1543 val
.native
= BN_is_negative(D
) ? -D
->d
[0] : D
->d
[0];
1550 for (; idx
>= 0; idx
--) {
1552 tmp
|= data
[idx
] & 0xff;
1558 val
.native
= negativ_num
? (RInt
) -tmp
: (RInt
) tmp
;
1560 end
: decode_length
+= buff
.increase_pos_padd(p_td
.raw
->padding
);
1562 return decode_length
+ prepaddlength
+ len_bits
;
1565 int INTEGER::XER_encode(const XERdescriptor_t
& p_td
, TTCN_Buffer
& p_buf
,
1566 unsigned int flavor
, int indent
, embed_values_enc_struct_t
*) const
1569 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND
,
1570 "Encoding an unbound integer value.");
1572 int encoded_length
= (int) p_buf
.get_len();
1574 flavor
|= SIMPLE_TYPE
;
1575 flavor
&= ~XER_RECOF
; // integer doesn't care
1576 if (begin_xml(p_td
, p_buf
, flavor
, indent
, false) == -1) --encoded_length
;
1580 tmp_str
= mprintf("%d", val
.native
);
1582 tmp_str
= BN_bn2dec(val
.openssl
);
1583 CHARSTRING
value(tmp_str
);
1587 OPENSSL_free(tmp_str
);
1588 p_buf
.put_string(value
);
1590 end_xml(p_td
, p_buf
, flavor
, indent
, false);
1592 return (int) p_buf
.get_len() - encoded_length
;
1595 int INTEGER::XER_decode(const XERdescriptor_t
& p_td
, XmlReaderWrap
& reader
,
1596 unsigned int flavor
, unsigned int /*flavor2*/, embed_values_dec_struct_t
*)
1598 const boolean exer
= is_exer(flavor
);
1599 int depth
= -1, success
= reader
.Ok(), type
;
1600 const char * value
= 0;
1602 boolean own_tag
= !(exer
&& (p_td
.xer_bits
& UNTAGGED
)) && !is_exerlist(flavor
);
1604 if (!own_tag
) goto tagless
;
1605 if (exer
&& (p_td
.xer_bits
& XER_ATTRIBUTE
)) {
1606 verify_name(reader
, p_td
, exer
);
1608 value
= (const char *)reader
.Value();
1610 for (; *value
&& isspace(*value
); ++value
) {}
1612 if (get_nof_digits() != (int)strlen(value
) - (value
[0] == '-') ? 1 : 0) {
1615 // Let the caller do reader.AdvanceAttribute();
1618 for (; success
== 1; success
= reader
.Read()) {
1619 type
= reader
.NodeType();
1620 if (XML_READER_TYPE_ELEMENT
== type
) {
1621 verify_name(reader
, p_td
, exer
);
1622 if (reader
.IsEmptyElement()) {
1623 if (exer
&& p_td
.dfeValue
!= 0) {
1624 *this = *static_cast<const INTEGER
*> (p_td
.dfeValue
);
1629 depth
= reader
.Depth();
1631 else if (XML_READER_TYPE_TEXT
== type
&& depth
!= -1) {
1632 value
= (const char*) reader
.Value();
1633 for (; *value
&& isspace(*value
); ++value
) {}
1635 if (get_nof_digits() != (int)strlen(value
) - (value
[0] == '-') ? 1 : 0) {
1639 else if (XML_READER_TYPE_END_ELEMENT
== type
) {
1640 verify_end(reader
, p_td
, depth
, exer
);
1641 if (!bound_flag
&& exer
&& p_td
.dfeValue
!= 0) {
1642 *this = *static_cast<const INTEGER
*> (p_td
.dfeValue
);
1648 } // if not attribute
1653 int INTEGER::get_nof_digits()
1657 RInt x
= val
.native
;
1658 if (x
== 0) return 1;
1665 BIGNUM
*x
= BN_new();
1666 BN_copy(x
, val
.openssl
);
1667 if (BN_is_zero(x
)) return 1;
1669 while (!BN_is_zero(x
)) {
1677 int INTEGER::JSON_encode(const TTCN_Typedescriptor_t
&, JSON_Tokenizer
& p_tok
) const
1680 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND
,
1681 "Encoding an unbound integer value.");
1686 tmp_str
= mprintf("%d", val
.native
);
1688 tmp_str
= BN_bn2dec(val
.openssl
);
1691 int enc_len
= p_tok
.put_next_token(JSON_TOKEN_NUMBER
, tmp_str
);
1696 OPENSSL_free(tmp_str
);
1702 int INTEGER::JSON_decode(const TTCN_Typedescriptor_t
& p_td
, JSON_Tokenizer
& p_tok
, boolean p_silent
)
1704 json_token_t token
= JSON_TOKEN_NONE
;
1706 size_t value_len
= 0;
1708 boolean use_default
= p_td
.json
->default_value
&& 0 == p_tok
.get_buffer_length();
1710 // No JSON data in the buffer -> use default value
1711 value
= (char*)p_td
.json
->default_value
;
1712 value_len
= strlen(value
);
1714 dec_len
= p_tok
.get_next_token(&token
, &value
, &value_len
);
1716 if (JSON_TOKEN_ERROR
== token
) {
1717 JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG
, JSON_DEC_BAD_TOKEN_ERROR
, "");
1718 return JSON_ERROR_FATAL
;
1720 else if (JSON_TOKEN_NUMBER
== token
|| use_default
) {
1721 char* number
= mcopystrn(value
, value_len
);
1722 if (from_string(number
) && (int)value_len
== get_nof_digits() + ('-' == value
[0] ? 1 : 0)) {
1725 JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG
, JSON_DEC_FORMAT_ERROR
, "number", "integer");
1727 dec_len
= JSON_ERROR_FATAL
;
1732 return JSON_ERROR_INVALID_TOKEN
;
1738 // Global functions.
1740 INTEGER
operator+(int int_value
, const INTEGER
& other_value
)
1742 other_value
.must_bound("Unbound right operand of integer addition.");
1743 return INTEGER(int_value
) + other_value
;
1746 INTEGER
operator-(int int_value
, const INTEGER
& other_value
)
1748 other_value
.must_bound("Unbound right operand of integer subtraction.");
1749 return INTEGER(int_value
) - other_value
;
1752 INTEGER
operator*(int int_value
, const INTEGER
& other_value
)
1754 other_value
.must_bound("Unbound right operand of integer multiplication.");
1755 return INTEGER(int_value
) * other_value
;
1758 INTEGER
operator/(int int_value
, const INTEGER
& other_value
)
1760 other_value
.must_bound("Unbound right operand of integer division.");
1761 if (other_value
.get_val() == 0)
1762 TTCN_error("Integer division by zero.");
1763 return INTEGER(int_value
) / other_value
;
1766 INTEGER
rem(int left_value
, int right_value
)
1768 if (right_value
== 0)
1769 TTCN_error("The right operand of rem operator is zero.");
1770 return INTEGER(left_value
- right_value
* (left_value
/ right_value
));
1773 INTEGER
rem(const INTEGER
& left_value
, const INTEGER
& right_value
)
1775 left_value
.must_bound("Unbound left operand of rem operator.");
1776 right_value
.must_bound("Unbound right operand of rem operator.");
1777 return left_value
- right_value
* (left_value
/ right_value
);
1780 INTEGER
rem(const INTEGER
& left_value
, int right_value
)
1782 left_value
.must_bound("Unbound left operand of rem operator.");
1783 return rem(left_value
, INTEGER(right_value
));
1786 INTEGER
rem(int left_value
, const INTEGER
& right_value
)
1788 right_value
.must_bound("Unbound right operand of rem operator.");
1789 return rem(INTEGER(left_value
), right_value
);
1792 INTEGER
mod(int left_value
, int right_value
)
1794 if (right_value
< 0) right_value
= -right_value
;
1795 else if (right_value
== 0)
1796 TTCN_error("The right operand of mod operator is zero.");
1797 if (left_value
> 0) return rem(left_value
, right_value
);
1799 int result
= rem(left_value
, right_value
);
1800 if (result
== 0) return 0;
1801 else return INTEGER(right_value
+ result
);
1805 INTEGER
mod(const INTEGER
& left_value
, const INTEGER
& right_value
)
1807 left_value
.must_bound("Unbound left operand of mod operator.");
1808 right_value
.must_bound("Unbound right operand of mod operator.");
1809 INTEGER
right_value_abs(right_value
);
1810 if (right_value
< 0) right_value_abs
= -right_value_abs
;
1811 else if (right_value
== 0)
1812 TTCN_error("The right operand of mod operator is zero.");
1813 if (left_value
> 0) {
1814 return rem(left_value
, right_value_abs
);
1816 INTEGER result
= rem(left_value
, right_value_abs
);
1817 if (result
== 0) return INTEGER((int)0);
1818 else return INTEGER(right_value_abs
+ result
);
1822 INTEGER
mod(const INTEGER
& left_value
, int right_value
)
1824 left_value
.must_bound("Unbound left operand of mod operator.");
1825 return mod(left_value
, INTEGER(right_value
));
1828 INTEGER
mod(int left_value
, const INTEGER
& right_value
)
1830 right_value
.must_bound("Unbound right operand of mod operator.");
1831 return mod(INTEGER(left_value
), right_value
);
1834 boolean
operator==(int int_value
, const INTEGER
& other_value
)
1836 other_value
.must_bound("Unbound right operand of integer comparison.");
1837 return INTEGER(int_value
) == other_value
;
1840 boolean
operator<(int int_value
, const INTEGER
& other_value
)
1842 other_value
.must_bound("Unbound right operand of integer comparison.");
1843 return INTEGER(int_value
) < other_value
;
1846 boolean
operator>(int int_value
, const INTEGER
& other_value
)
1848 other_value
.must_bound("Unbound right operand of integer comparison.");
1849 return INTEGER(int_value
) > other_value
;
1852 // Integer template class.
1854 void INTEGER_template::clean_up()
1856 switch (template_selection
) {
1857 case SPECIFIC_VALUE
:
1858 if (unlikely(!int_val
.native_flag
)) BN_free(int_val
.val
.openssl
);
1861 case COMPLEMENTED_LIST
:
1862 delete [] value_list
.list_value
;
1865 if (value_range
.min_is_present
&& unlikely(!value_range
.min_value
.native_flag
))
1866 BN_free(value_range
.min_value
.val
.openssl
);
1867 if (value_range
.max_is_present
&& unlikely(!value_range
.max_value
.native_flag
))
1868 BN_free(value_range
.max_value
.val
.openssl
);
1873 template_selection
= UNINITIALIZED_TEMPLATE
;
1876 void INTEGER_template::copy_template(const INTEGER_template
& other_value
)
1878 switch (other_value
.template_selection
) {
1879 case SPECIFIC_VALUE
:
1880 int_val
.native_flag
= other_value
.int_val
.native_flag
;
1881 if (likely(int_val
.native_flag
))
1882 int_val
.val
.native
= other_value
.int_val
.val
.native
;
1883 else int_val
.val
.openssl
= BN_dup(other_value
.int_val
.val
.openssl
);
1890 case COMPLEMENTED_LIST
:
1891 value_list
.n_values
= other_value
.value_list
.n_values
;
1892 value_list
.list_value
= new INTEGER_template
[value_list
.n_values
];
1893 for (unsigned int i
= 0; i
< value_list
.n_values
; i
++)
1894 value_list
.list_value
[i
].copy_template(
1895 other_value
.value_list
.list_value
[i
]);
1898 value_range
.min_is_present
= other_value
.value_range
.min_is_present
;
1899 if (value_range
.min_is_present
) {
1900 value_range
.min_value
.native_flag
= other_value
.value_range
.min_value
.native_flag
;
1901 if (likely(value_range
.min_value
.native_flag
))
1902 value_range
.min_value
.val
.native
=
1903 other_value
.value_range
.min_value
.val
.native
;
1905 value_range
.min_value
.val
.openssl
=
1906 BN_dup(other_value
.value_range
.min_value
.val
.openssl
);
1908 value_range
.max_is_present
= other_value
.value_range
.max_is_present
;
1909 if (value_range
.max_is_present
) {
1910 value_range
.max_value
.native_flag
= other_value
.value_range
.max_value
.native_flag
;
1911 if (likely(value_range
.max_value
.native_flag
))
1912 value_range
.max_value
.val
.native
=
1913 other_value
.value_range
.max_value
.val
.native
;
1915 value_range
.max_value
.val
.openssl
=
1916 BN_dup(other_value
.value_range
.max_value
.val
.openssl
);
1920 TTCN_error("Copying an uninitialized/unsupported integer template.");
1922 set_selection(other_value
);
1925 INTEGER_template::INTEGER_template()
1929 INTEGER_template::INTEGER_template(template_sel other_value
)
1930 : Base_Template(other_value
)
1932 check_single_selection(other_value
);
1935 INTEGER_template::INTEGER_template(int other_value
)
1936 : Base_Template(SPECIFIC_VALUE
)
1938 int_val
.native_flag
= TRUE
;
1939 int_val
.val
.native
= other_value
;
1942 INTEGER_template::INTEGER_template(const INTEGER
& other_value
)
1943 : Base_Template(SPECIFIC_VALUE
)
1945 other_value
.must_bound("Creating a template from an unbound integer "
1947 int_val_t other_value_int
= other_value
.get_val();
1948 int_val
.native_flag
= other_value_int
.native_flag
;
1949 if (likely(int_val
.native_flag
))
1950 int_val
.val
.native
= other_value_int
.val
.native
;
1951 else int_val
.val
.openssl
= BN_dup(other_value_int
.val
.openssl
);
1954 INTEGER_template::INTEGER_template(const OPTIONAL
<INTEGER
>& other_value
)
1956 switch (other_value
.get_selection()) {
1957 case OPTIONAL_PRESENT
: {
1958 set_selection(SPECIFIC_VALUE
);
1959 int_val_t other_value_int
= ((const INTEGER
&)other_value
).get_val();
1960 int_val
.native_flag
= other_value_int
.native_flag
;
1961 if (likely(int_val
.native_flag
))
1962 int_val
.val
.native
= other_value_int
.val
.native
;
1963 else int_val
.val
.openssl
= BN_dup(other_value_int
.val
.openssl
);
1966 set_selection(OMIT_VALUE
);
1969 TTCN_error("Creating an integer template from an unbound optional field.");
1973 INTEGER_template::INTEGER_template(const INTEGER_template
& other_value
)
1976 copy_template(other_value
);
1979 INTEGER_template::~INTEGER_template()
1984 INTEGER_template
& INTEGER_template::operator=(template_sel other_value
)
1986 check_single_selection(other_value
);
1988 set_selection(other_value
);
1992 INTEGER_template
& INTEGER_template::operator=(int other_value
)
1995 set_selection(SPECIFIC_VALUE
);
1996 int_val
.native_flag
= TRUE
;
1997 int_val
.val
.native
= other_value
;
2001 INTEGER_template
& INTEGER_template::operator=(const INTEGER
& other_value
)
2003 other_value
.must_bound("Assignment of an unbound integer value to a "
2006 set_selection(SPECIFIC_VALUE
);
2007 int_val_t other_value_int
= other_value
.get_val();
2008 int_val
.native_flag
= other_value_int
.native_flag
;
2009 if (likely(int_val
.native_flag
))
2010 int_val
.val
.native
= other_value_int
.val
.native
;
2011 else int_val
.val
.openssl
= BN_dup(other_value_int
.val
.openssl
);
2015 INTEGER_template
& INTEGER_template::operator=
2016 (const OPTIONAL
<INTEGER
>& other_value
)
2019 switch (other_value
.get_selection()) {
2020 case OPTIONAL_PRESENT
: {
2021 set_selection(SPECIFIC_VALUE
);
2022 int_val_t other_value_int
= ((const INTEGER
&)other_value
).get_val();
2023 int_val
.native_flag
= other_value_int
.native_flag
;
2024 if (likely(int_val
.native_flag
))
2025 int_val
.val
.native
= other_value_int
.val
.native
;
2026 else int_val
.val
.openssl
= BN_dup(other_value_int
.val
.openssl
);
2029 set_selection(OMIT_VALUE
);
2032 TTCN_error("Assignment of an unbound optional field to an integer "
2038 INTEGER_template
& INTEGER_template::operator=
2039 (const INTEGER_template
& other_value
)
2041 if (&other_value
!= this) {
2043 copy_template(other_value
);
2048 boolean
INTEGER_template::match(int other_value
, boolean
/* legacy */) const
2050 switch (template_selection
) {
2051 case SPECIFIC_VALUE
:
2052 if (likely(int_val
.native_flag
)) return int_val
.val
.native
== other_value
;
2053 return int_val_t(BN_dup(int_val
.val
.openssl
)) == other_value
;
2060 case COMPLEMENTED_LIST
:
2061 for(unsigned int i
= 0; i
< value_list
.n_values
; i
++)
2062 if (value_list
.list_value
[i
].match(other_value
))
2063 return template_selection
== VALUE_LIST
;
2064 return template_selection
== COMPLEMENTED_LIST
;
2066 boolean lower_boundary
= !value_range
.min_is_present
;
2067 boolean upper_boundary
= !value_range
.max_is_present
;
2068 // Lower boundary is set.
2069 if (!lower_boundary
) {
2070 lower_boundary
= (likely(value_range
.min_value
.native_flag
) ?
2071 int_val_t(value_range
.min_value
.val
.native
) :
2072 int_val_t(BN_dup(value_range
.min_value
.val
.openssl
))) <= other_value
;
2074 // Upper boundary is set.
2075 if (!upper_boundary
) {
2076 upper_boundary
= (likely(value_range
.max_value
.native_flag
) ?
2077 int_val_t(value_range
.max_value
.val
.native
) :
2078 int_val_t(BN_dup(value_range
.max_value
.val
.openssl
))) >= other_value
;
2080 return lower_boundary
&& upper_boundary
; }
2082 TTCN_error("Matching with an uninitialized/unsupported integer "
2088 boolean
INTEGER_template::match(const INTEGER
& other_value
,
2089 boolean
/* legacy */) const
2091 if (!other_value
.is_bound()) return FALSE
;
2092 switch (template_selection
) {
2093 case SPECIFIC_VALUE
: {
2094 int_val_t int_val_int
= likely(int_val
.native_flag
) ?
2095 int_val_t(int_val
.val
.native
) : int_val_t(BN_dup(int_val
.val
.openssl
));
2096 return int_val_int
== other_value
.get_val(); }
2103 case COMPLEMENTED_LIST
: // Merged cases.
2104 for (unsigned int i
= 0; i
< value_list
.n_values
; i
++)
2105 if (value_list
.list_value
[i
].match(other_value
))
2106 return template_selection
== VALUE_LIST
;
2107 return template_selection
== COMPLEMENTED_LIST
;
2109 boolean lower_boundary
= !value_range
.min_is_present
;
2110 boolean upper_boundary
= !value_range
.max_is_present
;
2111 // Lower boundary is set.
2112 if (!lower_boundary
) {
2113 lower_boundary
= (likely(value_range
.min_value
.native_flag
) ?
2114 int_val_t(value_range
.min_value
.val
.native
) :
2115 int_val_t(BN_dup(value_range
.min_value
.val
.openssl
))) <= other_value
.get_val();
2117 // Upper boundary is set.
2118 if (!upper_boundary
) {
2119 upper_boundary
= (likely(value_range
.max_value
.native_flag
) ?
2120 int_val_t(value_range
.max_value
.val
.native
) :
2121 int_val_t(BN_dup(value_range
.max_value
.val
.openssl
))) >= other_value
.get_val();
2123 return lower_boundary
&& upper_boundary
; }
2125 TTCN_error("Matching with an uninitialized/unsupported integer "
2131 INTEGER
INTEGER_template::valueof() const
2133 if (template_selection
!= SPECIFIC_VALUE
|| is_ifpresent
)
2134 TTCN_error("Performing a valueof or send operation on a non-specific "
2135 "integer template.");
2136 if (likely(int_val
.native_flag
)) return INTEGER(int_val
.val
.native
);
2137 else return INTEGER(BN_dup(int_val
.val
.openssl
));
2140 void INTEGER_template::set_type(template_sel template_type
,
2141 unsigned int list_length
)
2144 switch (template_type
) {
2146 case COMPLEMENTED_LIST
:
2147 set_selection(template_type
);
2148 value_list
.n_values
= list_length
;
2149 value_list
.list_value
= new INTEGER_template
[list_length
];
2152 set_selection(VALUE_RANGE
);
2153 value_range
.min_is_present
= FALSE
;
2154 value_range
.max_is_present
= FALSE
;
2157 TTCN_error("Setting an invalid type for an integer template.");
2161 INTEGER_template
& INTEGER_template::list_item(unsigned int list_index
)
2163 if (template_selection
!= VALUE_LIST
&&
2164 template_selection
!= COMPLEMENTED_LIST
)
2165 TTCN_error("Accessing a list element of a non-list integer template.");
2166 if (list_index
>= value_list
.n_values
)
2167 TTCN_error("Index overflow in an integer value list template.");
2168 return value_list
.list_value
[list_index
];
2171 void INTEGER_template::set_min(int min_value
)
2173 if (template_selection
!= VALUE_RANGE
)
2174 TTCN_error("Integer template is not range when setting lower limit.");
2175 if (value_range
.max_is_present
) {
2176 int_val_t max_value_int
= likely(value_range
.max_value
.native_flag
) ?
2177 int_val_t(value_range
.max_value
.val
.native
) :
2178 int_val_t(BN_dup(value_range
.max_value
.val
.openssl
));
2179 if (max_value_int
< min_value
)
2180 TTCN_error("The lower limit of the range is greater than the upper "
2181 "limit in an integer template.");
2183 value_range
.min_is_present
= TRUE
;
2184 value_range
.min_value
.native_flag
= TRUE
;
2185 value_range
.min_value
.val
.native
= min_value
;
2188 void INTEGER_template::set_min(const INTEGER
& min_value
)
2190 // Redundant, but performace matters. :)
2191 min_value
.must_bound("Using an unbound value when setting the lower bound "
2192 "in an integer range template.");
2193 if (template_selection
!= VALUE_RANGE
)
2194 TTCN_error("Integer template is not range when setting lower limit.");
2195 int_val_t min_value_int
= min_value
.get_val();
2196 if (value_range
.max_is_present
) {
2197 int_val_t max_value_int
= likely(value_range
.max_value
.native_flag
) ?
2198 int_val_t(value_range
.max_value
.val
.native
) :
2199 int_val_t(BN_dup(value_range
.max_value
.val
.openssl
));
2200 if (max_value_int
< min_value_int
)
2201 TTCN_error("The lower limit of the range is greater than the upper "
2202 "limit in an integer template.");
2204 value_range
.min_is_present
= TRUE
;
2205 value_range
.min_value
.native_flag
= min_value_int
.native_flag
;
2206 if (likely(value_range
.min_value
.native_flag
))
2207 value_range
.min_value
.val
.native
= min_value_int
.val
.native
;
2208 else value_range
.min_value
.val
.openssl
= BN_dup(min_value_int
.val
.openssl
);
2211 void INTEGER_template::set_max(int max_value
)
2213 if (template_selection
!= VALUE_RANGE
)
2214 TTCN_error("Integer template is not range when setting upper limit.");
2215 if (value_range
.min_is_present
) {
2216 int_val_t min_value_int
= likely(value_range
.min_value
.native_flag
) ?
2217 int_val_t(value_range
.min_value
.val
.native
) :
2218 int_val_t(BN_dup(value_range
.min_value
.val
.openssl
));
2219 if (min_value_int
> max_value
)
2220 TTCN_error("The upper limit of the range is smaller than the lower "
2221 "limit in an integer template.");
2223 value_range
.max_is_present
= TRUE
;
2224 value_range
.max_value
.native_flag
= TRUE
;
2225 value_range
.max_value
.val
.native
= max_value
;
2228 void INTEGER_template::set_max(const INTEGER
& max_value
)
2230 max_value
.must_bound("Using an unbound value when setting the upper bound "
2231 "in an integer range template.");
2232 if (template_selection
!= VALUE_RANGE
)
2233 TTCN_error("Integer template is not range when setting upper limit.");
2234 int_val_t max_value_int
= max_value
.get_val();
2235 if (value_range
.min_is_present
) {
2236 int_val_t min_value_int
= likely(value_range
.min_value
.native_flag
) ?
2237 int_val_t(value_range
.min_value
.val
.native
) :
2238 int_val_t(BN_dup(value_range
.min_value
.val
.openssl
));
2239 if (min_value_int
> max_value_int
)
2240 TTCN_error("The upper limit of the range is smaller than the lower "
2241 "limit in an integer template.");
2243 value_range
.max_is_present
= TRUE
;
2244 value_range
.max_value
.native_flag
= max_value_int
.native_flag
;
2245 if (likely(value_range
.max_value
.native_flag
))
2246 value_range
.max_value
.val
.native
= max_value_int
.val
.native
;
2247 else value_range
.max_value
.val
.openssl
= BN_dup(max_value_int
.val
.openssl
);
2250 void INTEGER_template::log() const
2252 switch (template_selection
) {
2253 case SPECIFIC_VALUE
: {
2254 int_val_t int_val_int
= likely(int_val
.native_flag
) ?
2255 int_val_t(int_val
.val
.native
) : int_val_t(BN_dup(int_val
.val
.openssl
));
2256 char *tmp_str
= int_val_int
.as_string();
2257 TTCN_Logger::log_event("%s", tmp_str
);
2260 case COMPLEMENTED_LIST
:
2261 TTCN_Logger::log_event_str("complement ");
2264 TTCN_Logger::log_char('(');
2265 for (unsigned int i
= 0; i
< value_list
.n_values
; i
++) {
2266 if (i
> 0) TTCN_Logger::log_event_str(", ");
2267 value_list
.list_value
[i
].log();
2269 TTCN_Logger::log_char(')');
2272 TTCN_Logger::log_char('(');
2273 if (value_range
.min_is_present
) {
2274 int_val_t min_value_int
= likely(value_range
.min_value
.native_flag
) ?
2275 int_val_t(value_range
.min_value
.val
.native
) :
2276 int_val_t(BN_dup(value_range
.min_value
.val
.openssl
));
2277 char *min_str
= min_value_int
.as_string();
2278 TTCN_Logger::log_event("%s", min_str
);
2281 TTCN_Logger::log_event_str("-infinity");
2283 TTCN_Logger::log_event_str(" .. ");
2284 if (value_range
.max_is_present
) {
2285 int_val_t max_value_int
= likely(value_range
.max_value
.native_flag
) ?
2286 int_val_t(value_range
.max_value
.val
.native
) :
2287 int_val_t(BN_dup(value_range
.max_value
.val
.openssl
));
2288 char *max_str
= max_value_int
.as_string();
2289 TTCN_Logger::log_event("%s", max_str
);
2292 TTCN_Logger::log_event_str("infinity");
2294 TTCN_Logger::log_char(')');
2303 void INTEGER_template::log_match(const INTEGER
& match_value
,
2304 boolean
/* legacy */) const
2306 if (TTCN_Logger::VERBOSITY_COMPACT
== TTCN_Logger::get_matching_verbosity()
2307 && TTCN_Logger::get_logmatch_buffer_len() != 0) {
2308 TTCN_Logger::print_logmatch_buffer();
2309 TTCN_Logger::log_event_str(" := ");
2312 TTCN_Logger::log_event_str(" with ");
2314 if (match(match_value
)) TTCN_Logger::log_event_str(" matched");
2315 else TTCN_Logger::log_event_str(" unmatched");
2318 void INTEGER_template::set_param(Module_Param
& param
) {
2319 param
.basic_check(Module_Param::BC_TEMPLATE
, "integer template");
2320 Module_Param_Ptr mp
= ¶m
;
2321 if (param
.get_type() == Module_Param::MP_Reference
) {
2322 mp
= param
.get_referenced_param();
2324 switch (mp
->get_type()) {
2325 case Module_Param::MP_Omit
:
2328 case Module_Param::MP_Any
:
2331 case Module_Param::MP_AnyOrNone
:
2332 *this = ANY_OR_OMIT
;
2334 case Module_Param::MP_List_Template
:
2335 case Module_Param::MP_ComplementList_Template
: {
2336 INTEGER_template temp
;
2337 temp
.set_type(mp
->get_type() == Module_Param::MP_List_Template
?
2338 VALUE_LIST
: COMPLEMENTED_LIST
, mp
->get_size());
2339 for (size_t i
=0; i
<mp
->get_size(); i
++) {
2340 temp
.list_item(i
).set_param(*mp
->get_elem(i
));
2344 case Module_Param::MP_Integer
: {
2346 tmp
.set_val(*mp
->get_integer());
2349 case Module_Param::MP_IntRange
: {
2350 set_type(VALUE_RANGE
);
2351 if (mp
->get_lower_int()!=NULL
) {
2353 tmp
.set_val(*mp
->get_lower_int());
2356 if (mp
->get_upper_int()!=NULL
) {
2358 tmp
.set_val(*mp
->get_upper_int());
2362 case Module_Param::MP_Expression
:
2363 switch (mp
->get_expr_type()) {
2364 case Module_Param::EXPR_NEGATE
: {
2366 operand
.set_param(*mp
->get_operand1());
2369 case Module_Param::EXPR_ADD
: {
2370 INTEGER operand1
, operand2
;
2371 operand1
.set_param(*mp
->get_operand1());
2372 operand2
.set_param(*mp
->get_operand2());
2373 *this = operand1
+ operand2
;
2375 case Module_Param::EXPR_SUBTRACT
: {
2376 INTEGER operand1
, operand2
;
2377 operand1
.set_param(*mp
->get_operand1());
2378 operand2
.set_param(*mp
->get_operand2());
2379 *this = operand1
- operand2
;
2381 case Module_Param::EXPR_MULTIPLY
: {
2382 INTEGER operand1
, operand2
;
2383 operand1
.set_param(*mp
->get_operand1());
2384 operand2
.set_param(*mp
->get_operand2());
2385 *this = operand1
* operand2
;
2387 case Module_Param::EXPR_DIVIDE
: {
2388 INTEGER operand1
, operand2
;
2389 operand1
.set_param(*mp
->get_operand1());
2390 operand2
.set_param(*mp
->get_operand2());
2391 if (operand2
== 0) {
2392 param
.error("Integer division by zero.");
2394 *this = operand1
/ operand2
;
2397 param
.expr_type_error("an integer");
2402 param
.type_error("integer template");
2404 is_ifpresent
= param
.get_ifpresent() || mp
->get_ifpresent();
2407 Module_Param
* INTEGER_template::get_param(Module_Param_Name
& param_name
) const
2409 Module_Param
* mp
= NULL
;
2410 switch (template_selection
) {
2411 case UNINITIALIZED_TEMPLATE
:
2412 mp
= new Module_Param_Unbound();
2415 mp
= new Module_Param_Omit();
2418 mp
= new Module_Param_Any();
2421 mp
= new Module_Param_AnyOrNone();
2423 case SPECIFIC_VALUE
:
2424 if (likely(int_val
.native_flag
)) {
2425 mp
= new Module_Param_Integer(new int_val_t(int_val
.val
.native
));
2428 mp
= new Module_Param_Integer(new int_val_t(BN_dup(int_val
.val
.openssl
)));
2432 case COMPLEMENTED_LIST
: {
2433 if (template_selection
== VALUE_LIST
) {
2434 mp
= new Module_Param_List_Template();
2437 mp
= new Module_Param_ComplementList_Template();
2439 for (size_t i
= 0; i
< value_list
.n_values
; ++i
) {
2440 mp
->add_elem(value_list
.list_value
[i
].get_param(param_name
));
2444 int_val_t
* lower_bound
= NULL
;
2445 int_val_t
* upper_bound
= NULL
;
2446 if (value_range
.min_is_present
) {
2447 if (value_range
.min_value
.native_flag
) {
2448 lower_bound
= new int_val_t(value_range
.min_value
.val
.native
);
2451 lower_bound
= new int_val_t(BN_dup(value_range
.min_value
.val
.openssl
));
2454 if (value_range
.max_is_present
) {
2455 if (value_range
.max_value
.native_flag
) {
2456 upper_bound
= new int_val_t(value_range
.max_value
.val
.native
);
2459 upper_bound
= new int_val_t(BN_dup(value_range
.max_value
.val
.openssl
));
2462 mp
= new Module_Param_IntRange(lower_bound
, upper_bound
);
2468 mp
->set_ifpresent();
2473 void INTEGER_template::encode_text(Text_Buf
& text_buf
) const
2475 encode_text_base(text_buf
);
2476 switch (template_selection
) {
2481 case SPECIFIC_VALUE
:
2482 text_buf
.push_int(likely(int_val
.native_flag
) ? int_val_t(int_val
.val
.native
)
2483 : int_val_t(BN_dup(int_val
.val
.openssl
)));
2486 case COMPLEMENTED_LIST
:
2487 text_buf
.push_int(value_list
.n_values
);
2488 for (unsigned int i
= 0; i
< value_list
.n_values
; i
++)
2489 value_list
.list_value
[i
].encode_text(text_buf
);
2492 text_buf
.push_int(value_range
.min_is_present
? 1 : 0);
2493 if (value_range
.min_is_present
)
2494 text_buf
.push_int(likely(value_range
.min_value
.native_flag
) ?
2495 int_val_t(value_range
.min_value
.val
.native
) :
2496 int_val_t(BN_dup(value_range
.min_value
.val
.openssl
)));
2497 text_buf
.push_int(value_range
.max_is_present
? 1 : 0);
2498 if (value_range
.max_is_present
)
2499 text_buf
.push_int(likely(value_range
.max_value
.native_flag
) ?
2500 int_val_t(value_range
.max_value
.val
.native
) :
2501 int_val_t(BN_dup(value_range
.max_value
.val
.openssl
)));
2504 TTCN_error("Text encoder: Encoding an uninitialized/unsupported integer "
2509 void INTEGER_template::decode_text(Text_Buf
& text_buf
)
2512 decode_text_base(text_buf
);
2513 switch (template_selection
) {
2518 case SPECIFIC_VALUE
: {
2519 int_val_t int_val_int
= text_buf
.pull_int();
2520 int_val
.native_flag
= int_val_int
.native_flag
;
2521 if (likely(int_val
.native_flag
)) int_val
.val
.native
= int_val_int
.val
.native
;
2522 else int_val
.val
.openssl
= BN_dup(int_val_int
.val
.openssl
);
2525 case COMPLEMENTED_LIST
:
2526 value_list
.n_values
= text_buf
.pull_int().get_val();
2527 value_list
.list_value
= new INTEGER_template
[value_list
.n_values
];
2528 for (unsigned int i
= 0; i
< value_list
.n_values
; i
++)
2529 value_list
.list_value
[i
].decode_text(text_buf
);
2532 value_range
.min_is_present
= text_buf
.pull_int() != 0;
2533 if (value_range
.min_is_present
) {
2534 int_val_t min_value_int
= text_buf
.pull_int();
2535 value_range
.min_value
.native_flag
= min_value_int
.native_flag
;
2536 if (likely(value_range
.min_value
.native_flag
))
2537 value_range
.min_value
.val
.native
= min_value_int
.val
.native
;
2538 else value_range
.min_value
.val
.openssl
= BN_dup(min_value_int
.val
.openssl
);
2540 value_range
.max_is_present
= text_buf
.pull_int() != 0;
2541 if (value_range
.max_is_present
) {
2542 int_val_t max_value_int
= text_buf
.pull_int();
2543 value_range
.max_value
.native_flag
= max_value_int
.native_flag
;
2544 if (likely(value_range
.max_value
.native_flag
))
2545 value_range
.max_value
.val
.native
= max_value_int
.val
.native
;
2546 else value_range
.max_value
.val
.openssl
= BN_dup(max_value_int
.val
.openssl
);
2550 TTCN_error("Text decoder: An unknown/unsupported selection was received "
2551 "for an integer template.");
2555 boolean
INTEGER_template::is_present(boolean legacy
/* = FALSE */) const
2557 if (template_selection
==UNINITIALIZED_TEMPLATE
) return FALSE
;
2558 return !match_omit(legacy
);
2561 boolean
INTEGER_template::match_omit(boolean legacy
/* = FALSE */) const
2563 if (is_ifpresent
) return TRUE
;
2564 switch (template_selection
) {
2569 case COMPLEMENTED_LIST
:
2571 // legacy behavior: 'omit' can appear in the value/complement list
2572 for (unsigned int i
=0; i
<value_list
.n_values
; i
++)
2573 if (value_list
.list_value
[i
].match_omit())
2574 return template_selection
==VALUE_LIST
;
2575 return template_selection
==COMPLEMENTED_LIST
;
2577 // else fall through
2584 #ifndef TITAN_RUNTIME_2
2585 void INTEGER_template::check_restriction(template_res t_res
, const char* t_name
,
2586 boolean legacy
/* = FALSE */) const
2588 if (template_selection
==UNINITIALIZED_TEMPLATE
) return;
2589 switch ((t_name
&&(t_res
==TR_VALUE
))?TR_OMIT
:t_res
) {
2591 if (!is_ifpresent
&& template_selection
==SPECIFIC_VALUE
) return;
2594 if (!is_ifpresent
&& (template_selection
==OMIT_VALUE
||
2595 template_selection
==SPECIFIC_VALUE
)) return;
2598 if (!match_omit(legacy
)) return;
2603 TTCN_error("Restriction `%s' on template of type %s violated.",
2604 get_res_name(t_res
), t_name
? t_name
: "integer");