1 /******************************************************************************
2 * Copyright (c) 2000-2016 Ericsson Telecom AB
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/epl-v10.html
20 * Szabo, Janos Zoltan – initial implementation
24 ******************************************************************************/
34 #include "Optional.hh"
36 #include "Param_Types.hh"
41 #include "Charstring.hh"
43 #include "XmlReader.hh"
45 #include <openssl/bn.h>
46 #include <openssl/crypto.h>
48 #include "../common/dbgnew.hh"
50 #if defined(__GNUC__) && __GNUC__ >= 3
51 // To provide prediction information for the compiler.
52 // Borrowed from /usr/src/linux/include/linux/compiler.h.
53 #define likely(x) __builtin_expect(!!(x), 1)
54 #define unlikely(x) __builtin_expect(!!(x), 0)
57 #define unlikely(x) (x)
60 static const Token_Match
integer_value_match("^([\t ]*-?[0-9]+).*$", TRUE
);
62 int_val_t
INTEGER::get_val() const
64 if (likely(native_flag
)) return int_val_t(val
.native
);
65 else return int_val_t(BN_dup(val
.openssl
));
68 void INTEGER::set_val(const int_val_t
& other_value
)
72 native_flag
= other_value
.native_flag
;
73 if (likely(native_flag
)) val
.native
= other_value
.val
.native
;
74 else val
.openssl
= BN_dup(other_value
.val
.openssl
);
83 INTEGER::INTEGER(int other_value
)
87 val
.native
= other_value
;
90 INTEGER::INTEGER(const INTEGER
& other_value
)
91 : Base_Type(other_value
)
93 other_value
.must_bound("Copying an unbound integer value.");
95 native_flag
= other_value
.native_flag
;
96 if (likely(native_flag
)) val
.native
= other_value
.val
.native
;
97 else val
.openssl
= BN_dup(other_value
.val
.openssl
);
100 /// Return 0 if fail, 1 on success
101 int INTEGER::from_string(const char *s
) {
102 BIGNUM
*other_value_int
= NULL
;
103 if (BN_dec2bn(&other_value_int
, s
+ (*s
== '+')))
106 if (BN_num_bits(other_value_int
) > (int)sizeof(int) * 8 - 1) {
108 val
.openssl
= other_value_int
;
111 val
.native
= string2RInt(s
);
112 BN_free(other_value_int
);
119 INTEGER::INTEGER(const char *other_value
)
121 if (unlikely(!other_value
))
122 TTCN_error("Unexpected error when converting `%s' to integer",
125 if (!from_string(other_value
)) TTCN_error(
126 "Unexpected error when converting `%s' to integer", other_value
);
129 // For internal use only. It's not part of the public interface.
130 INTEGER::INTEGER(BIGNUM
*other_value
)
132 if (unlikely(!other_value
))
133 TTCN_error("Unexpected error when initializing an integer");
136 val
.openssl
= other_value
;
141 if (!bound_flag
) return;
142 if (unlikely(!native_flag
)) BN_free(val
.openssl
);
145 void INTEGER::clean_up()
147 if (!bound_flag
) return;
148 if (unlikely(!native_flag
)) BN_free(val
.openssl
);
152 INTEGER
& INTEGER::operator=(int other_value
)
157 val
.native
= other_value
;
161 INTEGER
& INTEGER::operator=(const INTEGER
& other_value
)
163 if (this == &other_value
)
165 other_value
.must_bound("Assignment of an unbound integer value.");
168 native_flag
= other_value
.native_flag
;
169 if (likely(native_flag
)) val
.native
= other_value
.val
.native
;
170 else val
.openssl
= BN_dup(other_value
.val
.openssl
);
174 // A bit more specific than operator+().
175 INTEGER
& INTEGER::operator++()
177 must_bound("Unbound integer operand of unary increment operator.");
178 if (likely(native_flag
)) {
179 unsigned int result_u
= val
.native
+ 1;
180 int result
= val
.native
+ 1;
181 if (unlikely((static_cast<int>(result_u
) != result
) || (val
.native
> 0 && result
< 0))) {
182 BIGNUM
*val_openssl
= to_openssl(val
.native
);
183 BIGNUM
*one
= BN_new();
185 BN_add(val_openssl
, val_openssl
, one
);
188 val
.openssl
= val_openssl
;
193 BIGNUM
*one
= BN_new();
195 BN_add(val
.openssl
, val
.openssl
, one
);
201 // A bit more specific than operator-().
202 INTEGER
& INTEGER::operator--()
204 must_bound("Unbound integer operand of unary decrement operator.");
205 if (likely(native_flag
)) {
206 if (unlikely(val
.native
== INT_MIN
)) {
207 BIGNUM
*val_openssl
= to_openssl(val
.native
);
208 BIGNUM
*one
= BN_new();
210 BN_sub(val_openssl
, val_openssl
, one
);
213 val
.openssl
= val_openssl
;
218 BIGNUM
*one
= BN_new();
220 BN_sub(val
.openssl
, val
.openssl
, one
);
226 INTEGER
INTEGER::operator+() const
228 must_bound("Unbound integer operand of unary + operator.");
232 INTEGER
INTEGER::operator-() const
234 must_bound("Unbound integer operand of unary - operator (negation).");
235 if (likely(native_flag
)) {
236 if (unlikely(val
.native
== INT_MIN
)) {
237 BIGNUM
*result
= to_openssl(INT_MIN
);
238 BN_set_negative(result
, 0);
239 return INTEGER(result
);
241 return INTEGER(-val
.native
);
244 BIGNUM
*int_max_plus_one
= to_openssl(INT_MIN
);
245 BN_set_negative(int_max_plus_one
, 0);
246 int cmp
= BN_cmp(val
.openssl
, int_max_plus_one
);
247 BN_free(int_max_plus_one
);
248 if (unlikely(cmp
== 0)) {
249 return INTEGER(INT_MIN
);
251 BIGNUM
*result
= BN_dup(val
.openssl
);
252 BN_set_negative(result
, !BN_is_negative(result
));
253 return INTEGER(result
);
258 INTEGER
INTEGER::operator+(int other_value
) const
260 must_bound("Unbound left operand of integer addition.");
261 // Don't call out if slow. Implement this specific case right here.
262 return *this + INTEGER(other_value
);
265 INTEGER
INTEGER::operator+(const INTEGER
& other_value
) const
267 must_bound("Unbound left operand of integer addition.");
268 other_value
.must_bound("Unbound right operand of integer addition.");
269 // *this + other_value = *this add other_value
270 // *this + -other_value = *this sub other_value
271 // -*this + other_value = other_value sub *this
272 // -*this + -other_value = -(*this add other_value)
273 // Use only inline functions and BN_* directly. Call out for operator- in
275 boolean this_neg
= native_flag
? (val
.native
< 0)
276 : BN_is_negative(val
.openssl
);
277 boolean other_value_neg
= other_value
.native_flag
278 ? (other_value
.val
.native
< 0) : BN_is_negative(other_value
.val
.openssl
);
279 boolean result_neg
= this_neg
&& other_value_neg
;
280 if (!this_neg
&& other_value_neg
) return operator-(-other_value
);
281 if (this_neg
&& !other_value_neg
) return other_value
.operator-(-(*this));
282 if (likely(native_flag
)) {
283 if (likely(other_value
.native_flag
)) {
284 unsigned int result_u
= val
.native
+ other_value
.val
.native
;
285 int result
= val
.native
+ other_value
.val
.native
;
286 if ((static_cast<int>(result_u
) != result
) || (!result_neg
&&
287 result
< 0) || (result_neg
&& result
> 0)) {
288 // We can safely assume that the sum of two non-negative int values
289 // fit in an unsigned int. limits.h says:
290 // # define INT_MAX 2147483647
291 // # define UINT_MAX 4294967295
292 BIGNUM
*this_int
= to_openssl(val
.native
);
293 BIGNUM
*other_val_int
= to_openssl(other_value
.val
.native
);
294 BN_add(this_int
, this_int
, other_val_int
);
295 BN_free(other_val_int
);
296 return INTEGER(this_int
);
298 return INTEGER(result
);
301 // int (>= 0) + BIGNUM == BIGNUM.
302 BIGNUM
*this_int
= to_openssl(val
.native
);
303 BN_add(this_int
, this_int
, other_value
.val
.openssl
);
304 return INTEGER(this_int
);
307 // BIGNUM + int (>= 0) == BIGNUM.
308 BIGNUM
*result
= BN_new();
309 BIGNUM
*other_value_int
;
310 other_value_int
= other_value
.native_flag
311 ? to_openssl(other_value
.val
.native
) : other_value
.val
.openssl
;
312 BN_add(result
, val
.openssl
, other_value_int
);
313 if (likely(other_value
.native_flag
)) BN_free(other_value_int
);
314 return INTEGER(result
);
318 INTEGER
INTEGER::operator-(int other_value
) const
320 must_bound("Unbound left operand of integer subtraction.");
321 return *this - INTEGER(other_value
);
324 INTEGER
INTEGER::operator-(const INTEGER
& other_value
) const
326 must_bound("Unbound left operand of integer subtraction.");
327 other_value
.must_bound("Unbound right operand of integer subtraction.");
328 // *this - other_value = *this sub other_value
329 // -*this - other_value = -(*this add other_value)
330 // *this - -other_value = *this add other_value
331 // -*this - -other_value = -*this add other_value = other_value sub *this
332 boolean this_neg
= native_flag
? (val
.native
< 0)
333 : BN_is_negative(val
.openssl
);
334 boolean other_value_neg
= other_value
.native_flag
335 ? (other_value
.val
.native
< 0) : BN_is_negative(other_value
.val
.openssl
);
336 if (!this_neg
&& other_value_neg
) return operator+(-other_value
);
337 if (this_neg
&& !other_value_neg
) return -other_value
.operator+(-(*this));
338 if (likely(native_flag
)) {
339 if (likely(other_value
.native_flag
)) {
340 // Since both operands are non-negative the most negative result of a
341 // subtraction can be -INT_MAX and according to limits.h:
342 // # define INT_MIN (-INT_MAX - 1)
343 return INTEGER(val
.native
- other_value
.val
.native
);
345 BIGNUM
*this_int
= to_openssl(val
.native
);
346 BN_sub(this_int
, this_int
, other_value
.val
.openssl
);
347 // The result can be small enough to fit in int. Back conversion is a
348 // costly operation using strings all the time.
349 if (BN_num_bits(this_int
) <= (int)sizeof(int) * 8 - 1) {
350 char *result_str
= BN_bn2dec(this_int
);
351 RInt result
= string2RInt(result_str
);
352 OPENSSL_free(result_str
);
354 return INTEGER(result
);
356 return INTEGER(this_int
);
360 BIGNUM
*result
= BN_new();
361 BIGNUM
*other_value_int
= other_value
.native_flag
?
362 to_openssl(other_value
.val
.native
) : other_value
.val
.openssl
;
363 BN_sub(result
, val
.openssl
, other_value_int
);
364 if (other_value
.native_flag
) BN_free(other_value_int
);
365 if (BN_num_bits(result
) <= (int)sizeof(int) * 8 - 1) {
366 char *result_str
= BN_bn2dec(result
);
367 RInt result_int
= string2RInt(result_str
);
368 OPENSSL_free(result_str
);
370 return INTEGER(result_int
);
372 return INTEGER(result
);
377 INTEGER
INTEGER::operator*(int other_value
) const
379 must_bound("Unbound left operand of integer multiplication.");
380 return *this * INTEGER(other_value
);
383 INTEGER
INTEGER::operator*(const INTEGER
& other_value
) const
385 must_bound("Unbound left operand of integer multiplication.");
386 other_value
.must_bound("Unbound right operand of integer multiplication.");
387 if ((native_flag
&& val
.native
== 0) || (other_value
.native_flag
&&
388 other_value
.val
.native
== 0)) return INTEGER((int)0);
389 if (likely(native_flag
)) {
390 if (likely(other_value
.native_flag
)) {
392 if (likely(abs(val
.native
) < 32768 && abs(other_value
.val
.native
) < 32768)) {
393 return INTEGER(val
.native
* other_value
.val
.native
);
395 BIGNUM
*this_int
= to_openssl(val
.native
);
396 BIGNUM
*other_value_int
= to_openssl(other_value
.val
.native
);
397 BN_CTX
*ctx
= BN_CTX_new();
399 BN_mul(this_int
, this_int
, other_value_int
, ctx
);
401 BN_free(other_value_int
);
402 if (BN_num_bits(this_int
) < (int)sizeof(int) * 8) {
404 return INTEGER(val
.native
* other_value
.val
.native
);
406 return INTEGER(this_int
);
410 BIGNUM
*this_int
= to_openssl(val
.native
);
411 BN_CTX
*ctx
= BN_CTX_new();
413 BN_mul(this_int
, this_int
, other_value
.val
.openssl
, ctx
);
415 return INTEGER(this_int
);
418 BIGNUM
*result
= BN_new();
419 BIGNUM
*other_value_int
= NULL
;
420 BN_CTX
*ctx
= BN_CTX_new();
422 other_value_int
= other_value
.native_flag
423 ? to_openssl(other_value
.val
.native
) : other_value
.val
.openssl
;
424 BN_mul(result
, val
.openssl
, other_value_int
, ctx
);
426 if (likely(other_value
.native_flag
)) BN_free(other_value_int
);
427 return INTEGER(result
);
431 INTEGER
INTEGER::operator/(int other_value
) const
433 must_bound("Unbound left operand of integer division.");
434 if (other_value
== 0) TTCN_error("Integer division by zero.");
435 return *this / INTEGER(other_value
);
438 INTEGER
INTEGER::operator/(const INTEGER
& other_value
) const
440 must_bound("Unbound left operand of integer division.");
441 other_value
.must_bound("Unbound right operand of integer division.");
442 if (other_value
== 0) TTCN_error("Integer division by zero.");
443 if (native_flag
&& val
.native
== 0) return INTEGER((int)0);
444 if (likely(native_flag
)) {
445 if (likely(other_value
.native_flag
)) {
446 return INTEGER(val
.native
/ other_value
.val
.native
);
448 BIGNUM
*this_int
= to_openssl(val
.native
);
449 BN_CTX
*ctx
= BN_CTX_new();
451 BN_div(this_int
, NULL
, this_int
, other_value
.val
.openssl
, ctx
);
453 if (BN_num_bits(this_int
) <= (int)sizeof(int) * 8 - 1) {
454 char *result_str
= BN_bn2dec(this_int
);
455 RInt result
= string2RInt(result_str
);
456 OPENSSL_free(result_str
);
458 return INTEGER(result
);
460 return INTEGER(this_int
);
464 BIGNUM
*result
= BN_new();
465 BIGNUM
*other_value_int
= NULL
;
466 BN_CTX
*ctx
= BN_CTX_new();
468 other_value_int
= other_value
.native_flag
469 ? to_openssl(other_value
.val
.native
) : other_value
.val
.openssl
;
470 BN_div(result
, NULL
, val
.openssl
, other_value_int
, ctx
);
471 if (likely(other_value
.native_flag
)) BN_free(other_value_int
);
473 if (BN_num_bits(result
) <= (int)sizeof(int) * 8 - 1) {
474 char *result_str
= BN_bn2dec(result
);
475 RInt result_i
= string2RInt(result_str
);
476 OPENSSL_free(result_str
);
478 return INTEGER(result_i
);
480 return INTEGER(result
);
485 boolean
INTEGER::operator==(int other_value
) const
487 must_bound("Unbound left operand of integer comparison.");
488 if (likely(native_flag
)) {
489 return val
.native
== other_value
;
491 BIGNUM
*other_value_int
= to_openssl(other_value
);
492 int equal
= BN_cmp(val
.openssl
, other_value_int
);
493 BN_free(other_value_int
);
498 boolean
INTEGER::operator==(const INTEGER
& other_value
) const
500 must_bound("Unbound left operand of integer comparison.");
501 other_value
.must_bound("Unbound right operand of integer comparison.");
502 if (likely(native_flag
)) {
503 if (likely(other_value
.native_flag
)) {
504 return val
.native
== other_value
.val
.native
;
506 BIGNUM
*this_int
= to_openssl(val
.native
);
507 int equal
= BN_cmp(this_int
, other_value
.val
.openssl
);
512 if (likely(other_value
.native_flag
)) {
513 BIGNUM
*other_value_int
= to_openssl(other_value
.val
.native
);
514 int equal
= BN_cmp(val
.openssl
, other_value_int
);
515 BN_free(other_value_int
);
518 return BN_cmp(val
.openssl
, other_value
.val
.openssl
) == 0;
523 boolean
INTEGER::operator<(int other_value
) const
525 must_bound("Unbound left operand of integer comparison.");
526 return *this < INTEGER(other_value
);
529 boolean
INTEGER::operator<(const INTEGER
& other_value
) const
531 must_bound("Unbound left operand of integer comparison.");
532 other_value
.must_bound("Unbound right operand of integer comparison.");
533 if (likely(native_flag
)) {
534 if (likely(other_value
.native_flag
)) {
535 return val
.native
< other_value
.val
.native
;
537 BIGNUM
*this_int
= to_openssl(val
.native
);
538 int equal
= BN_cmp(this_int
, other_value
.val
.openssl
);
543 if (likely(other_value
.native_flag
)) {
544 BIGNUM
*other_value_int
= to_openssl(other_value
.val
.native
);
545 int equal
= BN_cmp(val
.openssl
, other_value_int
);
546 BN_free(other_value_int
);
549 return BN_cmp(val
.openssl
, other_value
.val
.openssl
) == -1;
554 boolean
INTEGER::operator>(int other_value
) const
556 must_bound("Unbound left operand of integer comparison.");
557 return *this > INTEGER(other_value
);
560 boolean
INTEGER::operator>(const INTEGER
& other_value
) const
562 // A simple call to operator< and operator== would be much simplier.
563 must_bound("Unbound left operand of integer comparison.");
564 other_value
.must_bound("Unbound right operand of integer comparison.");
565 if (likely(native_flag
)) {
566 if (likely(other_value
.native_flag
)) {
567 return val
.native
> other_value
.val
.native
;
569 BIGNUM
*this_int
= to_openssl(val
.native
);
570 int equal
= BN_cmp(this_int
, other_value
.val
.openssl
);
575 if (likely(other_value
.native_flag
)) {
576 BIGNUM
*other_value_int
= to_openssl(other_value
.val
.native
);
577 int equal
= BN_cmp(val
.openssl
, other_value_int
);
578 BN_free(other_value_int
);
581 return BN_cmp(val
.openssl
, other_value
.val
.openssl
) == 1;
586 INTEGER::operator int() const
588 must_bound("Using the value of an unbound integer variable.");
589 if (unlikely(!native_flag
))
590 TTCN_error("Invalid conversion of a large integer value");
594 // To avoid ambiguity we have a separate function to convert our INTEGER
595 // object to long long.
596 long long int INTEGER::get_long_long_val() const
598 must_bound("Using the value of an unbound integer variable.");
599 if (likely(native_flag
)) return val
.native
;
600 size_t slot_size
= sizeof(BN_ULONG
);
601 bool is_negative
= BN_is_negative(val
.openssl
);
602 long long int ret_val
= 0;
603 if (unlikely(val
.openssl
->top
== 0)) return 0;
604 // It feels so bad accessing a BIGNUM directly, but faster than string
606 else if (likely(val
.openssl
->top
== 1))
607 return !is_negative
? val
.openssl
->d
[0] : -val
.openssl
->d
[0];
608 ret_val
= val
.openssl
->d
[val
.openssl
->top
- 1];
609 // From now, shift by 8.
610 for (int i
= val
.openssl
->top
- 2; i
>= 0; i
--) {
611 for (int j
= slot_size
- 1; j
>= 0; j
--) {
612 unsigned char tmp
= (val
.openssl
->d
[i
] >> 8 * j
) & 0xff;
617 return !is_negative
? ret_val
: -ret_val
;
620 void INTEGER::set_long_long_val(long long int other_value
)
624 // Seems to be a native. It's very strange if someone calls this with a
625 // small number. A simple assignment should be used for such values.
626 if (unlikely((RInt
)other_value
== other_value
)) {
628 val
.native
= other_value
;
632 val
.openssl
= BN_new();
634 BN_zero(val
.openssl
);
635 bool is_negative
= other_value
< 0;
636 unsigned long long int tmp
= !is_negative
? other_value
: -other_value
;
637 for (int i
= sizeof(long long int) - 1; i
>= 0; i
--) {
638 BN_add_word(val
.openssl
, (tmp
>> 8 * i
) & 0xff);
639 if (i
) BN_lshift(val
.openssl
, val
.openssl
, 8);
641 BN_set_negative(val
.openssl
, is_negative
? 1 : 0);
644 void INTEGER::log() const
646 if (likely(bound_flag
)) {
647 if (likely(native_flag
)) {
648 TTCN_Logger::log_event("%d", val
.native
);
650 char *tmp
= BN_bn2dec(val
.openssl
);
651 TTCN_Logger::log_event("%s", tmp
);
655 TTCN_Logger::log_event_unbound();
659 void INTEGER::set_param(Module_Param
& param
)
661 param
.basic_check(Module_Param::BC_VALUE
, "integer value");
662 Module_Param_Ptr mp
= ¶m
;
663 if (param
.get_type() == Module_Param::MP_Reference
) {
664 mp
= param
.get_referenced_param();
666 switch (mp
->get_type()) {
667 case Module_Param::MP_Integer
: {
670 const int_val_t
* const int_val
= mp
->get_integer();
671 native_flag
= int_val
->is_native();
672 if (likely(native_flag
)){
673 val
.native
= int_val
->get_val();
675 val
.openssl
= BN_dup(int_val
->get_val_openssl());
678 case Module_Param::MP_Expression
:
679 switch (mp
->get_expr_type()) {
680 case Module_Param::EXPR_NEGATE
: {
682 operand
.set_param(*mp
->get_operand1());
685 case Module_Param::EXPR_ADD
: {
686 INTEGER operand1
, operand2
;
687 operand1
.set_param(*mp
->get_operand1());
688 operand2
.set_param(*mp
->get_operand2());
689 *this = operand1
+ operand2
;
691 case Module_Param::EXPR_SUBTRACT
: {
692 INTEGER operand1
, operand2
;
693 operand1
.set_param(*mp
->get_operand1());
694 operand2
.set_param(*mp
->get_operand2());
695 *this = operand1
- operand2
;
697 case Module_Param::EXPR_MULTIPLY
: {
698 INTEGER operand1
, operand2
;
699 operand1
.set_param(*mp
->get_operand1());
700 operand2
.set_param(*mp
->get_operand2());
701 *this = operand1
* operand2
;
703 case Module_Param::EXPR_DIVIDE
: {
704 INTEGER operand1
, operand2
;
705 operand1
.set_param(*mp
->get_operand1());
706 operand2
.set_param(*mp
->get_operand2());
708 param
.error("Integer division by zero.");
710 *this = operand1
/ operand2
;
713 param
.expr_type_error("an integer");
718 param
.type_error("integer value");
723 Module_Param
* INTEGER::get_param(Module_Param_Name
& /* param_name */) const
726 return new Module_Param_Unbound();
729 return new Module_Param_Integer(new int_val_t(val
.native
));
731 return new Module_Param_Integer(new int_val_t(BN_dup(val
.openssl
)));
734 void INTEGER::encode_text(Text_Buf
& text_buf
) const
736 must_bound("Text encoder: Encoding an unbound integer value.");
737 if (likely(native_flag
)) {
738 text_buf
.push_int(val
.native
);
740 int_val_t
*tmp
= new int_val_t(BN_dup(val
.openssl
));
741 text_buf
.push_int(*tmp
);
746 void INTEGER::decode_text(Text_Buf
& text_buf
)
750 int_val_t
tmp(text_buf
.pull_int());
751 if (likely(tmp
.native_flag
)) {
753 val
.native
= tmp
.get_val();
756 val
.openssl
= BN_dup(tmp
.get_val_openssl());
760 void INTEGER::encode(const TTCN_Typedescriptor_t
& p_td
, TTCN_Buffer
& p_buf
,
761 TTCN_EncDec::coding_t p_coding
, ...) const
764 va_start(pvar
, p_coding
);
766 case TTCN_EncDec::CT_BER
: {
767 TTCN_EncDec_ErrorContext
ec("While BER-encoding type '%s': ", p_td
.name
);
768 unsigned BER_coding
=va_arg(pvar
, unsigned);
769 BER_encode_chk_coding(BER_coding
);
770 ASN_BER_TLV_t
*tlv
=BER_encode_TLV(p_td
, BER_coding
);
771 tlv
->put_in_buffer(p_buf
);
772 ASN_BER_TLV_t::destruct(tlv
);
774 case TTCN_EncDec::CT_RAW
: {
775 TTCN_EncDec_ErrorContext
ec("While RAW-encoding type '%s': ", p_td
.name
);
777 TTCN_EncDec_ErrorContext::error_internal
778 ("No RAW descriptor available for type '%s'.", p_td
.name
);
782 RAW_enc_tree
root(TRUE
,NULL
,&rp
,1,p_td
.raw
);
783 RAW_encode(p_td
, root
);
784 root
.put_to_buf(p_buf
);
786 case TTCN_EncDec::CT_TEXT
: {
787 TTCN_EncDec_ErrorContext
ec("While TEXT-encoding type '%s': ", p_td
.name
);
789 TTCN_EncDec_ErrorContext::error_internal
790 ("No TEXT descriptor available for type '%s'.", p_td
.name
);
791 TEXT_encode(p_td
,p_buf
);
793 case TTCN_EncDec::CT_XER
: {
794 TTCN_EncDec_ErrorContext
ec("While XER-encoding type '%s': ", p_td
.name
);
795 unsigned XER_coding
=va_arg(pvar
, unsigned);
796 XER_encode(*p_td
.xer
, p_buf
, XER_coding
, 0, 0);
798 case TTCN_EncDec::CT_JSON
: {
799 TTCN_EncDec_ErrorContext
ec("While JSON-encoding type '%s': ", p_td
.name
);
801 TTCN_EncDec_ErrorContext::error_internal
802 ("No JSON descriptor available for type '%s'.", p_td
.name
);
803 JSON_Tokenizer
tok(va_arg(pvar
, int) != 0);
804 JSON_encode(p_td
, tok
);
805 p_buf
.put_s(tok
.get_buffer_length(), (const unsigned char*)tok
.get_buffer());
808 TTCN_error("Unknown coding method requested to encode type '%s'",
814 void INTEGER::decode(const TTCN_Typedescriptor_t
& p_td
, TTCN_Buffer
& p_buf
,
815 TTCN_EncDec::coding_t p_coding
, ...)
818 va_start(pvar
, p_coding
);
820 case TTCN_EncDec::CT_BER
: {
821 TTCN_EncDec_ErrorContext
ec("While BER-decoding type '%s': ", p_td
.name
);
822 unsigned L_form
=va_arg(pvar
, unsigned);
824 BER_decode_str2TLV(p_buf
, tlv
, L_form
);
825 BER_decode_TLV(p_td
, tlv
, L_form
);
826 if(tlv
.isComplete
) p_buf
.increase_pos(tlv
.get_len());
828 case TTCN_EncDec::CT_RAW
: {
829 TTCN_EncDec_ErrorContext
ec("While RAW-decoding type '%s': ", p_td
.name
);
831 TTCN_EncDec_ErrorContext::error_internal
832 ("No RAW descriptor available for type '%s'.", p_td
.name
);
834 switch(p_td
.raw
->top_bit_order
){
842 if(RAW_decode(p_td
, p_buf
, p_buf
.get_len()*8, order
)<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_TEXT
: {
849 Limit_Token_List limit
;
850 TTCN_EncDec_ErrorContext
ec("While TEXT-decoding type '%s': ", p_td
.name
);
852 TTCN_EncDec_ErrorContext::error_internal
853 ("No TEXT descriptor available for type '%s'.", p_td
.name
);
854 const unsigned char *b
=p_buf
.get_data();
855 if(b
[p_buf
.get_len()-1]!='\0'){
856 p_buf
.set_pos(p_buf
.get_len());
857 p_buf
.put_zero(8,ORDER_LSB
);
860 if(TEXT_decode(p_td
,p_buf
,limit
)<0)
861 ec
.error(TTCN_EncDec::ET_INCOMPL_MSG
,
862 "Can not decode type '%s', because invalid or incomplete"
863 " message was received"
866 case TTCN_EncDec::CT_XER
: {
867 TTCN_EncDec_ErrorContext
ec("While XER-decoding type '%s': ", p_td
.name
);
868 unsigned XER_coding
=va_arg(pvar
, unsigned);
869 XmlReaderWrap
reader(p_buf
);
870 for (int success
= reader
.Read(); success
==1; success
=reader
.Read()) {
871 int type
= reader
.NodeType();
872 if (type
==XML_READER_TYPE_ELEMENT
)
875 XER_decode(*p_td
.xer
, reader
, XER_coding
, XER_NONE
, 0);
876 size_t bytes
= reader
.ByteConsumed();
877 p_buf
.set_pos(bytes
);
879 case TTCN_EncDec::CT_JSON
: {
880 TTCN_EncDec_ErrorContext
ec("While JSON-decoding type '%s': ", p_td
.name
);
882 TTCN_EncDec_ErrorContext::error_internal
883 ("No JSON descriptor available for type '%s'.", p_td
.name
);
884 JSON_Tokenizer
tok((const char*)p_buf
.get_data(), p_buf
.get_len());
885 if(JSON_decode(p_td
, tok
, false)<0)
886 ec
.error(TTCN_EncDec::ET_INCOMPL_MSG
,
887 "Can not decode type '%s', because invalid or incomplete"
888 " message was received"
890 p_buf
.set_pos(tok
.get_buf_pos());
893 TTCN_error("Unknown coding method requested to decode type '%s'",
899 ASN_BER_TLV_t
*INTEGER::BER_encode_TLV(const TTCN_Typedescriptor_t
& p_td
,
900 unsigned p_coding
) const
903 ASN_BER_TLV_t
*new_tlv
= BER_encode_chk_bound(is_bound());
906 new_tlv
= BER_encode_TLV_INTEGER(p_coding
, val
.native
);
909 int_val_t
*tmp
= new int_val_t(BN_dup(val
.openssl
));
910 new_tlv
= BER_encode_TLV_INTEGER(p_coding
, *tmp
);
914 new_tlv
= ASN_BER_V2TLV(new_tlv
, p_td
, p_coding
);
918 boolean
INTEGER::BER_decode_TLV(const TTCN_Typedescriptor_t
& p_td
,
919 const ASN_BER_TLV_t
& p_tlv
,
925 ASN_BER_TLV_t stripped_tlv
;
926 BER_decode_strip_tags(*p_td
.ber
, p_tlv
, L_form
, stripped_tlv
);
927 TTCN_EncDec_ErrorContext
ec("While decoding INTEGER type: ");
929 boolean ret_val
= BER_decode_TLV_INTEGER(stripped_tlv
, L_form
, tmp
);
930 if (tmp
.is_native()) {
932 val
.native
= tmp
.get_val();
935 val
.openssl
= BN_dup(tmp
.get_val_openssl());
937 if (ret_val
) bound_flag
= TRUE
;
941 int INTEGER::TEXT_decode(const TTCN_Typedescriptor_t
& p_td
,
942 TTCN_Buffer
& buff
, Limit_Token_List
& limit
, boolean no_err
, boolean
/*first_call*/)
944 int decoded_length
= 0;
946 if (p_td
.text
->begin_decode
) {
948 if ((tl
= p_td
.text
->begin_decode
->match_begin(buff
)) < 0) {
949 if (no_err
) return -1;
950 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_TOKEN_ERR
,
951 "The specified token '%s' not found for '%s': ",
952 (const char*)*(p_td
.text
->begin_decode
), p_td
.name
);
955 decoded_length
+= tl
;
956 buff
.increase_pos(tl
);
958 if (buff
.get_read_len() <= 1 && no_err
) return -TTCN_EncDec::ET_LEN_ERR
;
959 if (p_td
.text
->select_token
) {
961 if ((tl
= p_td
.text
->select_token
->match_begin(buff
)) < 0) {
962 if (no_err
) return -1;
966 } else if ( p_td
.text
->val
.parameters
967 && p_td
.text
->val
.parameters
->decoding_params
.min_length
!= -1) {
968 str_len
= p_td
.text
->val
.parameters
->decoding_params
.min_length
;
969 } else if (p_td
.text
->end_decode
) {
971 if ((tl
= p_td
.text
->end_decode
->match_first(buff
)) < 0) {
972 if (no_err
) return -1;
976 } else if (limit
.has_token()) {
978 if ((tl
= limit
.match(buff
)) < 0) {
979 if (no_err
) return -1;
985 if ((tl
= integer_value_match
.match_begin(buff
)) < 0) {
986 if (no_err
) return -1;
994 char *atm
= (char*)Malloc(str_len
+ 1); // sizeof(char) == 1 by definition
995 const char *b
= (const char*)buff
.get_read_data();
996 memcpy(atm
, b
, str_len
);
1001 int neg
= *atm
== 0x2d ? 1 : 0;
1002 if (!*(atm
+ neg
)) {
1003 for (offs
= neg
; *(atm
+ offs
) == 0x30; offs
++) ; // E.g. 0, -0, 00001234, -00001234.
1004 if (neg
&& offs
> 1) *(atm
+ offs
- 1) = *atm
; // E.g. -00001234 -> -000-1234.
1007 for(; atm
[offs
] == 0x20; offs
++) ;
1010 if (0 == strlen(atm
+ offs
) || 0 == from_string(atm
+offs
)) {
1016 buff
.increase_pos(str_len
);
1017 decoded_length
+= str_len
;
1022 if (no_err
) return -1;
1023 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_TOKEN_ERR
,
1024 "Can not decode a valid integer for '%s': ", p_td
.name
);
1026 if (p_td
.text
->end_decode
) {
1028 if ((tl
= p_td
.text
->end_decode
->match_begin(buff
)) < 0) {
1029 if (no_err
) return -1;
1030 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_TOKEN_ERR
,
1031 "The specified token '%s' not found for '%s': ",
1032 (const char*)*(p_td
.text
->end_decode
), p_td
.name
);
1035 decoded_length
+= tl
;
1036 buff
.increase_pos(tl
);
1039 return decoded_length
;
1042 int INTEGER::TEXT_encode(const TTCN_Typedescriptor_t
& p_td
,
1043 TTCN_Buffer
& buff
) const
1045 int encoded_length
= 0;
1046 if (p_td
.text
->begin_encode
) {
1047 buff
.put_cs(*p_td
.text
->begin_encode
);
1048 encoded_length
+= p_td
.text
->begin_encode
->lengthof();
1051 TTCN_EncDec_ErrorContext::error
1052 (TTCN_EncDec::ET_UNBOUND
,"Encoding an unbound value.");
1053 if (p_td
.text
->end_encode
) {
1054 buff
.put_cs(*p_td
.text
->end_encode
);
1055 encoded_length
+=p_td
.text
->end_encode
->lengthof();
1057 return encoded_length
;
1061 if (native_flag
) tmp_str
= mprintf("%d", val
.native
);
1062 else tmp_str
= BN_bn2dec(val
.openssl
);
1063 CHARSTRING
ch(tmp_str
);
1064 if (native_flag
) Free(tmp_str
);
1065 else OPENSSL_free(tmp_str
);
1066 if (p_td
.text
->val
.parameters
== NULL
) {
1068 encoded_length
+= ch
.lengthof();
1070 TTCN_TEXTdescriptor_values params
= p_td
.text
->val
.parameters
1072 if (params
.min_length
< 0) {
1074 encoded_length
+= ch
.lengthof();
1076 unsigned char *p
= NULL
;
1078 size_t len
= params
.min_length
+ 1;
1079 buff
.get_end(p
, len
);
1080 if (params
.leading_zero
) {
1082 a
= snprintf((char*)p
, len
, "%0*d", params
.min_length
, val
.native
);
1084 int chlen
= ch
.lengthof(), pad
= 0;
1085 int neg
= native_flag
? (val
.native
< 0) : BN_is_negative(val
.openssl
);
1086 if (params
.min_length
> chlen
)
1087 pad
= params
.min_length
- chlen
+ neg
;
1090 memset(p
+ neg
, 0x30, pad
);
1091 for (int i
= 0; i
< chlen
- neg
; i
++)
1092 p
[i
+ pad
] = ch
[i
+ neg
].get_char();
1093 a
+= pad
+ chlen
- neg
;
1096 a
= snprintf((char*)p
, len
, "%*s", p_td
.text
->val
.parameters
->
1097 coding_params
.min_length
, (const char*)ch
);
1099 buff
.increase_length(a
);
1100 encoded_length
+= a
;
1103 if (p_td
.text
->end_encode
) {
1104 buff
.put_cs(*p_td
.text
->end_encode
);
1105 encoded_length
+= p_td
.text
->end_encode
->lengthof();
1107 return encoded_length
;
1110 unsigned char INTX_MASKS
[] = { 0 /*dummy*/, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF };
1112 int INTEGER::RAW_encode(const TTCN_Typedescriptor_t
& p_td
, RAW_enc_tree
& myleaf
) const
1114 if (!native_flag
) return RAW_encode_openssl(p_td
, myleaf
);
1116 int length
; // total length, in bytes
1117 int val_bits
= 0, len_bits
= 0; // only for IntX
1118 int value
= val
.native
;
1119 boolean neg_sgbit
= (value
< 0) && (p_td
.raw
->comp
== SG_SG_BIT
);
1121 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND
,
1122 "Encoding an unbound value.");
1126 if (value
!= 0 && value
== -value
) {
1127 // value == -INT_MAX-1 a.k.a. INT_MIN a.k.a. 0x8000....
1128 INTEGER
big_value(to_openssl(val
.native
)); // too big for native
1129 return big_value
.RAW_encode_openssl(p_td
, myleaf
);
1131 if ((value
< 0) && (p_td
.raw
->comp
== SG_NO
)) {
1132 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_SIGN_ERR
,
1133 "Unsigned encoding of a negative number: %s", p_td
.name
);
1136 if (neg_sgbit
) value
= -value
;
1137 //myleaf.ext_bit=EXT_BIT_NO;
1138 if (myleaf
.must_free
) Free(myleaf
.body
.leaf
.data_ptr
);
1139 if (p_td
.raw
->fieldlength
== RAW_INTX
) { // IntX (variable length)
1140 val_bits
= (p_td
.raw
->comp
!= SG_NO
); // bits needed to store the value
1142 if (v2
< 0 && p_td
.raw
->comp
== SG_2COMPL
) {
1150 len_bits
= 1 + val_bits
/ 8; // bits needed to store the length
1151 if (val_bits
% 8 + len_bits
% 8 > 8) {
1152 // the remainder of the value bits and the length bits do not fit into
1153 // an octet => an extra octet is needed and the length must be increased
1156 length
= (len_bits
+ val_bits
+ 7) / 8;
1157 if (len_bits
% 8 == 0 && val_bits
% 8 != 0) {
1158 // special case: the value can be stored on 8k - 1 octets plus the partial octet
1159 // - len_bits = 8k is not enough, since there's no partial octet in that case
1160 // and the length would then be followed by 8k octets (and it only indicates
1161 // 8k - 1 further octets)
1162 // - len_bits = 8k + 1 is too much, since there are only 8k - 1 octets
1163 // following the partial octet (and 8k are indicated)
1164 // solution: len_bits = 8k + 1 and insert an extra empty octet
1169 else { // not IntX, use the field length
1170 length
= (p_td
.raw
->fieldlength
+ 7) / 8;
1171 if (min_bits(value
) > p_td
.raw
->fieldlength
) {
1172 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_LEN_ERR
,
1173 "There are insufficient bits to encode '%s' : ", p_td
.name
);
1174 value
= 0; // substitute with zero
1177 if (length
> RAW_INT_ENC_LENGTH
) { // does not fit in the small buffer
1178 myleaf
.body
.leaf
.data_ptr
= bc
= (unsigned char*)Malloc(length
* sizeof(*bc
));
1179 myleaf
.must_free
= TRUE
;
1180 myleaf
.data_ptr_used
= TRUE
;
1182 else bc
= myleaf
.body
.leaf
.data_array
;
1183 if (p_td
.raw
->fieldlength
== RAW_INTX
) {
1185 // treat the empty space between the value and the length as if it was part
1186 // of the value, too
1187 val_bits
= length
* 8 - len_bits
;
1188 // first, encode the value
1190 bc
[i
] = value
& INTX_MASKS
[val_bits
> 8 ? 8 : val_bits
];
1195 while (val_bits
> 0);
1197 // the sign bit is the first bit after the length
1198 unsigned char mask
= 0x80 >> len_bits
% 8;
1201 // second, encode the length (ignore the last zero)
1203 if (val_bits
!= 0) {
1204 // the remainder of the length is in the same octet as the remainder of the
1205 // value => step back onto it
1209 // the remainder of the length is in a separate octet
1212 // insert the length's partial octet
1213 unsigned char mask
= 0x80;
1214 for (int j
= 0; j
< len_bits
% 8; ++j
) {
1218 if (len_bits
% 8 > 0 || val_bits
!= 0) {
1219 // there was a partial octet => step onto the first full octet
1222 // insert the length's full octets
1223 while (len_bits
>= 8) {
1224 // octets containing only ones in the length
1229 myleaf
.length
= length
* 8;
1232 for (int a
= 0; a
< length
; a
++) {
1233 bc
[a
] = value
& 0xFF;
1237 unsigned char mask
= 0x01 << (p_td
.raw
->fieldlength
- 1) % 8;
1238 bc
[length
- 1] |= mask
;
1240 myleaf
.length
= p_td
.raw
->fieldlength
;
1242 return myleaf
.length
;
1245 int INTEGER::RAW_encode_openssl(const TTCN_Typedescriptor_t
& p_td
,
1246 RAW_enc_tree
& myleaf
) const
1248 unsigned char *bc
= NULL
;
1249 int length
; // total length, in bytes
1250 int val_bits
= 0, len_bits
= 0; // only for IntX
1251 BIGNUM
*D
= BN_new();
1252 BN_copy(D
, val
.openssl
);
1253 boolean neg_sgbit
= (D
->neg
) && (p_td
.raw
->comp
== SG_SG_BIT
);
1255 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND
,
1256 "Encoding an unbound value.");
1260 if ((D
->neg
) && (p_td
.raw
->comp
== SG_NO
)) {
1261 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_SIGN_ERR
,
1262 "Unsigned encoding of a negative number: %s", p_td
.name
);
1263 BN_set_negative(D
, 0);
1266 // `if (neg_sgbit) tmp->neg = tmp->neg == 0;' is not needed, because the
1267 // sign is stored separately from the number. Default encoding of negative
1268 // values in 2's complement form.
1269 if (myleaf
.must_free
) Free(myleaf
.body
.leaf
.data_ptr
);
1270 if (p_td
.raw
->fieldlength
== RAW_INTX
) {
1271 val_bits
= BN_num_bits(D
) + (p_td
.raw
->comp
!= SG_NO
); // bits needed to store the value
1272 len_bits
= 1 + val_bits
/ 8; // bits needed to store the length
1273 if (val_bits
% 8 + len_bits
% 8 > 8) {
1274 // the remainder of the value bits and the length bits do not fit into
1275 // an octet => an extra octet is needed and the length must be increased
1278 length
= (len_bits
+ val_bits
+ 7) / 8;
1279 if (len_bits
% 8 == 0 && val_bits
% 8 != 0) {
1280 // special case: the value can be stored on 8k - 1 octets plus the partial octet
1281 // - len_bits = 8k is not enough, since there's no partial octet in that case
1282 // and the length would then be followed by 8k octets (and it only indicates
1283 // 8k - 1 further octets)
1284 // - len_bits = 8k + 1 is too much, since there are only 8k - 1 octets
1285 // following the partial octet (and 8k are indicated)
1286 // solution: len_bits = 8k + 1 and insert an extra empty octet
1292 length
= (p_td
.raw
->fieldlength
+ 7) / 8;
1293 if (min_bits(D
) > p_td
.raw
->fieldlength
) {
1294 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_LEN_ERR
,
1295 "There are insufficient bits to encode '%s': ", p_td
.name
);
1296 // `tmp = -((-tmp) & BitMaskTable[min_bits(tmp)]);' doesn't make any sense
1297 // at all for negative values. Just simply clear the value.
1302 if (length
> RAW_INT_ENC_LENGTH
) {
1303 myleaf
.body
.leaf
.data_ptr
= bc
=
1304 (unsigned char *)Malloc(length
* sizeof(*bc
));
1305 myleaf
.must_free
= TRUE
;
1306 myleaf
.data_ptr_used
= TRUE
;
1308 bc
= myleaf
.body
.leaf
.data_array
;
1310 boolean twos_compl
= (D
->neg
) && !neg_sgbit
;
1311 // Conversion to 2's complement.
1313 BN_set_negative(D
, 0);
1314 for (int a
= 0; a
< D
->dmax
; a
++) D
->d
[a
] = ~D
->d
[a
];
1317 if (p_td
.raw
->fieldlength
== RAW_INTX
) {
1319 // treat the empty space between the value and the length as if it was part
1320 // of the value, too
1321 val_bits
= length
* 8 - len_bits
;
1322 // first, encode the value
1324 bc
[i
] = (D
->top
? D
->d
[0] : (twos_compl
? 0xFF : 0)) & INTX_MASKS
[val_bits
> 8 ? 8 : val_bits
];
1329 while (val_bits
> 0);
1331 // the sign bit is the first bit after the length
1332 unsigned char mask
= 0x80 >> len_bits
% 8;
1335 // second, encode the length (ignore the last zero)
1337 if (val_bits
!= 0) {
1338 // the remainder of the length is in the same octet as the remainder of the
1339 // value => step back onto it
1343 // the remainder of the length is in a separate octet
1346 // insert the length's partial octet
1347 unsigned char mask
= 0x80;
1348 for (int j
= 0; j
< len_bits
% 8; ++j
) {
1352 if (len_bits
% 8 > 0 || val_bits
!= 0) {
1353 // there was a partial octet => step onto the first full octet
1356 // insert the length's full octets
1357 while (len_bits
>= 8) {
1358 // octets containing only ones in the length
1363 myleaf
.length
= length
* 8;
1366 int num_bytes
= BN_num_bytes(D
);
1367 for (int a
= 0; a
< length
; a
++) {
1368 if (twos_compl
&& num_bytes
- 1 < a
) bc
[a
] = 0xff;
1369 else bc
[a
] = (D
->top
? D
->d
[0] : 0) & 0xff;
1373 unsigned char mask
= 0x01 << (p_td
.raw
->fieldlength
- 1) % 8;
1374 bc
[length
- 1] |= mask
;
1377 myleaf
.length
= p_td
.raw
->fieldlength
;
1379 return myleaf
.length
;
1382 int INTEGER::RAW_decode(const TTCN_Typedescriptor_t
& p_td
, TTCN_Buffer
& buff
,
1383 int limit
, raw_order_t top_bit_ord
, boolean no_err
, int /*sel_field*/,
1384 boolean
/*first_call*/)
1387 int prepaddlength
= buff
.increase_pos_padd(p_td
.raw
->prepadding
);
1388 limit
-= prepaddlength
;
1390 boolean orders
= FALSE
;
1391 if (p_td
.raw
->bitorderinoctet
== ORDER_MSB
) orders
= TRUE
;
1392 if (p_td
.raw
->bitorderinfield
== ORDER_MSB
) orders
= !orders
;
1393 cp
.bitorder
= orders
? ORDER_MSB
: ORDER_LSB
;
1395 if (p_td
.raw
->byteorder
== ORDER_MSB
) orders
= TRUE
;
1396 if (p_td
.raw
->bitorderinfield
== ORDER_MSB
) orders
= !orders
;
1397 cp
.byteorder
= orders
? ORDER_MSB
: ORDER_LSB
;
1398 cp
.fieldorder
= p_td
.raw
->fieldorder
;
1399 cp
.hexorder
= ORDER_LSB
;
1400 int decode_length
= 0;
1401 int len_bits
= 0; // only for IntX (amount of bits used to store the length)
1402 unsigned char len_data
= 0; // only for IntX (an octet used to store the length)
1403 int partial_octet_bits
= 0; // only for IntX (amount of value bits in the partial octet)
1404 if (p_td
.raw
->fieldlength
== RAW_INTX
) {
1405 // extract the length
1407 // check if at least 8 bits are available in the buffer
1410 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_LEN_ERR
,
1411 "There are not enough bits in the buffer to decode the length of IntX "
1412 "type %s (needed: %d, found: %d).", p_td
.name
, len_bits
+ 8,
1415 return -TTCN_EncDec::ET_LEN_ERR
;
1420 int nof_unread_bits
= buff
.unread_len_bit();
1421 if (nof_unread_bits
< 8) {
1423 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_INCOMPL_MSG
,
1424 "There are not enough bits in the buffer to decode the length of IntX "
1425 "type %s (needed: %d, found: %d).", p_td
.name
, len_bits
+ 8,
1426 len_bits
+ nof_unread_bits
);
1428 return -TTCN_EncDec::ET_INCOMPL_MSG
;
1431 // extract the next length octet (or partial length octet)
1432 buff
.get_b(8, &len_data
, cp
, top_bit_ord
);
1433 unsigned char mask
= 0x80;
1436 if (len_data
& mask
) {
1440 // the first zero signals the end of the length
1441 // the rest of the bits in the octet are part of the value
1442 partial_octet_bits
= (8 - len_bits
% 8) % 8;
1444 // decode_length only stores the amount of bits in full octets needed
1445 // by the value, the bits in the partial octet are stored by len_data
1446 decode_length
= 8 * (len_bits
- 1);
1450 while (len_bits
% 8 != 0);
1452 while (decode_length
== 0 && partial_octet_bits
== 0);
1455 // not IntX, use the static field length
1456 decode_length
= p_td
.raw
->fieldlength
;
1458 if (decode_length
> limit
) {
1460 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_LEN_ERR
,
1461 "There are not enough bits in the buffer to decode%s type %s (needed: %d, "
1462 "found: %d).", p_td
.raw
->fieldlength
== RAW_INTX
? " the value of IntX" : "",
1463 p_td
.name
, decode_length
, limit
);
1465 if (no_err
|| p_td
.raw
->fieldlength
== RAW_INTX
) {
1466 return -TTCN_EncDec::ET_LEN_ERR
;
1468 decode_length
= limit
;
1470 int nof_unread_bits
= buff
.unread_len_bit();
1471 if (decode_length
> nof_unread_bits
) {
1473 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_INCOMPL_MSG
,
1474 "There are not enough bits in the buffer to decode%s type %s (needed: %d, "
1475 "found: %d).", p_td
.raw
->fieldlength
== RAW_INTX
? " the value of IntX" : "",
1476 p_td
.name
, decode_length
, nof_unread_bits
);
1478 if (no_err
|| p_td
.raw
->fieldlength
== RAW_INTX
) {
1479 return -TTCN_EncDec::ET_INCOMPL_MSG
;
1481 decode_length
= nof_unread_bits
;
1484 if (decode_length
< 0) return -1;
1485 else if (decode_length
== 0 && partial_octet_bits
== 0) {
1492 unsigned char *data
= (unsigned char *) Malloc(
1493 (decode_length
+ partial_octet_bits
+ 7) / 8);
1494 buff
.get_b((size_t) decode_length
, data
, cp
, top_bit_ord
);
1495 if (partial_octet_bits
!= 0) {
1496 // in case there are value bits in the last length octet (only for IntX),
1497 // these need to be appended to the extracted data
1498 data
[decode_length
/ 8] = len_data
;
1499 decode_length
+= partial_octet_bits
;
1501 int end_pos
= decode_length
;
1502 int idx
= (end_pos
- 1) / 8;
1503 boolean negativ_num
= FALSE
;
1504 switch (p_td
.raw
->comp
) {
1506 if (data
[idx
] >> ((end_pos
- 1) % 8) & 0x01) {
1514 negativ_num
= (data
[idx
] >> ((end_pos
- 1) % 8)) & 0x01;
1522 tmp
|= data
[0] & BitMaskTable
[end_pos
];
1525 idx
= (end_pos
- 1) / 8;
1526 tmp
<<= (end_pos
- 1) % 8 + 1;
1527 tmp
|= data
[idx
--] & BitMaskTable
[(end_pos
- 1) % 8 + 1];
1528 if (decode_length
> (RInt
) sizeof(RInt
) * 8 - 1) {
1529 BIGNUM
*D
= BN_new();
1530 BN_set_word(D
, tmp
);
1531 int pad
= tmp
== 0 ? 1 : 0;
1532 for (; idx
>= 0; idx
--) {
1533 if (pad
&& data
[idx
] != 0) {
1534 BN_set_word(D
, data
[idx
] & 0xff);
1540 BN_add_word(D
, data
[idx
] & 0xff);
1543 BIGNUM
*D_tmp
= BN_new();
1544 BN_set_bit(D_tmp
, BN_num_bits(D
));
1545 BN_sub(D
, D
, D_tmp
);
1548 else if (negativ_num
) {
1549 BN_set_negative(D
, 1);
1551 // Back to native. "BN_num_bits(D) + BN_is_negative(D) >
1552 // (RInt)sizeof(RInt) * 8 - !BN_is_negative(D)" was an over-complicated
1554 if (BN_num_bits(D
) > (RInt
) sizeof(RInt
) * 8 - 1) {
1555 native_flag
= FALSE
;
1560 val
.native
= BN_is_negative(D
) ? -D
->d
[0] : D
->d
[0];
1567 for (; idx
>= 0; idx
--) {
1569 tmp
|= data
[idx
] & 0xff;
1575 val
.native
= negativ_num
? (RInt
) -tmp
: (RInt
) tmp
;
1577 end
: decode_length
+= buff
.increase_pos_padd(p_td
.raw
->padding
);
1579 return decode_length
+ prepaddlength
+ len_bits
;
1582 int INTEGER::XER_encode(const XERdescriptor_t
& p_td
, TTCN_Buffer
& p_buf
,
1583 unsigned int flavor
, int indent
, embed_values_enc_struct_t
*) const
1586 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND
,
1587 "Encoding an unbound integer value.");
1589 int encoded_length
= (int) p_buf
.get_len();
1591 flavor
|= SIMPLE_TYPE
;
1592 flavor
&= ~XER_RECOF
; // integer doesn't care
1593 if (begin_xml(p_td
, p_buf
, flavor
, indent
, false) == -1) --encoded_length
;
1597 tmp_str
= mprintf("%d", val
.native
);
1599 tmp_str
= BN_bn2dec(val
.openssl
);
1600 CHARSTRING
value(tmp_str
);
1604 OPENSSL_free(tmp_str
);
1605 p_buf
.put_string(value
);
1607 end_xml(p_td
, p_buf
, flavor
, indent
, false);
1609 return (int) p_buf
.get_len() - encoded_length
;
1612 int INTEGER::XER_decode(const XERdescriptor_t
& p_td
, XmlReaderWrap
& reader
,
1613 unsigned int flavor
, unsigned int /*flavor2*/, embed_values_dec_struct_t
*)
1615 const boolean exer
= is_exer(flavor
);
1616 int depth
= -1, success
= reader
.Ok(), type
;
1617 const char * value
= 0;
1619 boolean own_tag
= !(exer
&& (p_td
.xer_bits
& UNTAGGED
)) && !is_exerlist(flavor
);
1621 if (!own_tag
) goto tagless
;
1622 if (exer
&& (p_td
.xer_bits
& XER_ATTRIBUTE
)) {
1623 verify_name(reader
, p_td
, exer
);
1625 value
= (const char *)reader
.Value();
1627 for (; *value
&& isspace(*value
); ++value
) {}
1629 if (get_nof_digits() != (int)strlen(value
) - (value
[0] == '-') ? 1 : 0) {
1632 // Let the caller do reader.AdvanceAttribute();
1635 for (; success
== 1; success
= reader
.Read()) {
1636 type
= reader
.NodeType();
1637 if (XML_READER_TYPE_ELEMENT
== type
) {
1638 verify_name(reader
, p_td
, exer
);
1639 if (reader
.IsEmptyElement()) {
1640 if (exer
&& p_td
.dfeValue
!= 0) {
1641 *this = *static_cast<const INTEGER
*> (p_td
.dfeValue
);
1646 depth
= reader
.Depth();
1648 else if (XML_READER_TYPE_TEXT
== type
&& depth
!= -1) {
1649 value
= (const char*) reader
.Value();
1650 for (; *value
&& isspace(*value
); ++value
) {}
1652 if (get_nof_digits() != (int)strlen(value
) - (value
[0] == '-') ? 1 : 0) {
1656 else if (XML_READER_TYPE_END_ELEMENT
== type
) {
1657 verify_end(reader
, p_td
, depth
, exer
);
1658 if (!bound_flag
&& exer
&& p_td
.dfeValue
!= 0) {
1659 *this = *static_cast<const INTEGER
*> (p_td
.dfeValue
);
1665 } // if not attribute
1670 int INTEGER::get_nof_digits()
1674 RInt x
= val
.native
;
1675 if (x
== 0) return 1;
1682 BIGNUM
*x
= BN_new();
1683 BN_copy(x
, val
.openssl
);
1684 if (BN_is_zero(x
)) return 1;
1686 while (!BN_is_zero(x
)) {
1694 int INTEGER::JSON_encode(const TTCN_Typedescriptor_t
&, JSON_Tokenizer
& p_tok
) const
1697 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND
,
1698 "Encoding an unbound integer value.");
1703 tmp_str
= mprintf("%d", val
.native
);
1705 tmp_str
= BN_bn2dec(val
.openssl
);
1708 int enc_len
= p_tok
.put_next_token(JSON_TOKEN_NUMBER
, tmp_str
);
1713 OPENSSL_free(tmp_str
);
1719 int INTEGER::JSON_decode(const TTCN_Typedescriptor_t
& p_td
, JSON_Tokenizer
& p_tok
, boolean p_silent
)
1721 json_token_t token
= JSON_TOKEN_NONE
;
1723 size_t value_len
= 0;
1725 boolean use_default
= p_td
.json
->default_value
&& 0 == p_tok
.get_buffer_length();
1727 // No JSON data in the buffer -> use default value
1728 value
= (char*)p_td
.json
->default_value
;
1729 value_len
= strlen(value
);
1731 dec_len
= p_tok
.get_next_token(&token
, &value
, &value_len
);
1733 if (JSON_TOKEN_ERROR
== token
) {
1734 JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG
, JSON_DEC_BAD_TOKEN_ERROR
, "");
1735 return JSON_ERROR_FATAL
;
1737 else if (JSON_TOKEN_NUMBER
== token
|| use_default
) {
1738 char* number
= mcopystrn(value
, value_len
);
1739 if (from_string(number
) && (int)value_len
== get_nof_digits() + ('-' == value
[0] ? 1 : 0)) {
1742 JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG
, JSON_DEC_FORMAT_ERROR
, "number", "integer");
1744 dec_len
= JSON_ERROR_FATAL
;
1749 return JSON_ERROR_INVALID_TOKEN
;
1755 // Global functions.
1757 INTEGER
operator+(int int_value
, const INTEGER
& other_value
)
1759 other_value
.must_bound("Unbound right operand of integer addition.");
1760 return INTEGER(int_value
) + other_value
;
1763 INTEGER
operator-(int int_value
, const INTEGER
& other_value
)
1765 other_value
.must_bound("Unbound right operand of integer subtraction.");
1766 return INTEGER(int_value
) - other_value
;
1769 INTEGER
operator*(int int_value
, const INTEGER
& other_value
)
1771 other_value
.must_bound("Unbound right operand of integer multiplication.");
1772 return INTEGER(int_value
) * other_value
;
1775 INTEGER
operator/(int int_value
, const INTEGER
& other_value
)
1777 other_value
.must_bound("Unbound right operand of integer division.");
1778 if (other_value
.get_val() == 0)
1779 TTCN_error("Integer division by zero.");
1780 return INTEGER(int_value
) / other_value
;
1783 INTEGER
rem(int left_value
, int right_value
)
1785 if (right_value
== 0)
1786 TTCN_error("The right operand of rem operator is zero.");
1787 return INTEGER(left_value
- right_value
* (left_value
/ right_value
));
1790 INTEGER
rem(const INTEGER
& left_value
, const INTEGER
& right_value
)
1792 left_value
.must_bound("Unbound left operand of rem operator.");
1793 right_value
.must_bound("Unbound right operand of rem operator.");
1794 return left_value
- right_value
* (left_value
/ right_value
);
1797 INTEGER
rem(const INTEGER
& left_value
, int right_value
)
1799 left_value
.must_bound("Unbound left operand of rem operator.");
1800 return rem(left_value
, INTEGER(right_value
));
1803 INTEGER
rem(int left_value
, const INTEGER
& right_value
)
1805 right_value
.must_bound("Unbound right operand of rem operator.");
1806 return rem(INTEGER(left_value
), right_value
);
1809 INTEGER
mod(int left_value
, int right_value
)
1811 if (right_value
< 0) right_value
= -right_value
;
1812 else if (right_value
== 0)
1813 TTCN_error("The right operand of mod operator is zero.");
1814 if (left_value
> 0) return rem(left_value
, right_value
);
1816 int result
= rem(left_value
, right_value
);
1817 if (result
== 0) return 0;
1818 else return INTEGER(right_value
+ result
);
1822 INTEGER
mod(const INTEGER
& left_value
, const INTEGER
& right_value
)
1824 left_value
.must_bound("Unbound left operand of mod operator.");
1825 right_value
.must_bound("Unbound right operand of mod operator.");
1826 INTEGER
right_value_abs(right_value
);
1827 if (right_value
< 0) right_value_abs
= -right_value_abs
;
1828 else if (right_value
== 0)
1829 TTCN_error("The right operand of mod operator is zero.");
1830 if (left_value
> 0) {
1831 return rem(left_value
, right_value_abs
);
1833 INTEGER result
= rem(left_value
, right_value_abs
);
1834 if (result
== 0) return INTEGER((int)0);
1835 else return INTEGER(right_value_abs
+ result
);
1839 INTEGER
mod(const INTEGER
& left_value
, int right_value
)
1841 left_value
.must_bound("Unbound left operand of mod operator.");
1842 return mod(left_value
, INTEGER(right_value
));
1845 INTEGER
mod(int left_value
, const INTEGER
& right_value
)
1847 right_value
.must_bound("Unbound right operand of mod operator.");
1848 return mod(INTEGER(left_value
), right_value
);
1851 boolean
operator==(int int_value
, const INTEGER
& other_value
)
1853 other_value
.must_bound("Unbound right operand of integer comparison.");
1854 return INTEGER(int_value
) == other_value
;
1857 boolean
operator<(int int_value
, const INTEGER
& other_value
)
1859 other_value
.must_bound("Unbound right operand of integer comparison.");
1860 return INTEGER(int_value
) < other_value
;
1863 boolean
operator>(int int_value
, const INTEGER
& other_value
)
1865 other_value
.must_bound("Unbound right operand of integer comparison.");
1866 return INTEGER(int_value
) > other_value
;
1869 // Integer template class.
1871 void INTEGER_template::clean_up()
1873 switch (template_selection
) {
1874 case SPECIFIC_VALUE
:
1875 if (unlikely(!int_val
.native_flag
)) BN_free(int_val
.val
.openssl
);
1878 case COMPLEMENTED_LIST
:
1879 delete [] value_list
.list_value
;
1882 if (value_range
.min_is_present
&& unlikely(!value_range
.min_value
.native_flag
))
1883 BN_free(value_range
.min_value
.val
.openssl
);
1884 if (value_range
.max_is_present
&& unlikely(!value_range
.max_value
.native_flag
))
1885 BN_free(value_range
.max_value
.val
.openssl
);
1890 template_selection
= UNINITIALIZED_TEMPLATE
;
1893 void INTEGER_template::copy_template(const INTEGER_template
& other_value
)
1895 switch (other_value
.template_selection
) {
1896 case SPECIFIC_VALUE
:
1897 int_val
.native_flag
= other_value
.int_val
.native_flag
;
1898 if (likely(int_val
.native_flag
))
1899 int_val
.val
.native
= other_value
.int_val
.val
.native
;
1900 else int_val
.val
.openssl
= BN_dup(other_value
.int_val
.val
.openssl
);
1907 case COMPLEMENTED_LIST
:
1908 value_list
.n_values
= other_value
.value_list
.n_values
;
1909 value_list
.list_value
= new INTEGER_template
[value_list
.n_values
];
1910 for (unsigned int i
= 0; i
< value_list
.n_values
; i
++)
1911 value_list
.list_value
[i
].copy_template(
1912 other_value
.value_list
.list_value
[i
]);
1915 value_range
.min_is_present
= other_value
.value_range
.min_is_present
;
1916 if (value_range
.min_is_present
) {
1917 value_range
.min_value
.native_flag
= other_value
.value_range
.min_value
.native_flag
;
1918 if (likely(value_range
.min_value
.native_flag
))
1919 value_range
.min_value
.val
.native
=
1920 other_value
.value_range
.min_value
.val
.native
;
1922 value_range
.min_value
.val
.openssl
=
1923 BN_dup(other_value
.value_range
.min_value
.val
.openssl
);
1925 value_range
.max_is_present
= other_value
.value_range
.max_is_present
;
1926 if (value_range
.max_is_present
) {
1927 value_range
.max_value
.native_flag
= other_value
.value_range
.max_value
.native_flag
;
1928 if (likely(value_range
.max_value
.native_flag
))
1929 value_range
.max_value
.val
.native
=
1930 other_value
.value_range
.max_value
.val
.native
;
1932 value_range
.max_value
.val
.openssl
=
1933 BN_dup(other_value
.value_range
.max_value
.val
.openssl
);
1937 TTCN_error("Copying an uninitialized/unsupported integer template.");
1939 set_selection(other_value
);
1942 INTEGER_template::INTEGER_template()
1946 INTEGER_template::INTEGER_template(template_sel other_value
)
1947 : Base_Template(other_value
)
1949 check_single_selection(other_value
);
1952 INTEGER_template::INTEGER_template(int other_value
)
1953 : Base_Template(SPECIFIC_VALUE
)
1955 int_val
.native_flag
= TRUE
;
1956 int_val
.val
.native
= other_value
;
1959 INTEGER_template::INTEGER_template(const INTEGER
& other_value
)
1960 : Base_Template(SPECIFIC_VALUE
)
1962 other_value
.must_bound("Creating a template from an unbound integer "
1964 int_val_t other_value_int
= other_value
.get_val();
1965 int_val
.native_flag
= other_value_int
.native_flag
;
1966 if (likely(int_val
.native_flag
))
1967 int_val
.val
.native
= other_value_int
.val
.native
;
1968 else int_val
.val
.openssl
= BN_dup(other_value_int
.val
.openssl
);
1971 INTEGER_template::INTEGER_template(const OPTIONAL
<INTEGER
>& other_value
)
1973 switch (other_value
.get_selection()) {
1974 case OPTIONAL_PRESENT
: {
1975 set_selection(SPECIFIC_VALUE
);
1976 int_val_t other_value_int
= ((const INTEGER
&)other_value
).get_val();
1977 int_val
.native_flag
= other_value_int
.native_flag
;
1978 if (likely(int_val
.native_flag
))
1979 int_val
.val
.native
= other_value_int
.val
.native
;
1980 else int_val
.val
.openssl
= BN_dup(other_value_int
.val
.openssl
);
1983 set_selection(OMIT_VALUE
);
1986 TTCN_error("Creating an integer template from an unbound optional field.");
1990 INTEGER_template::INTEGER_template(const INTEGER_template
& other_value
)
1993 copy_template(other_value
);
1996 INTEGER_template::~INTEGER_template()
2001 INTEGER_template
& INTEGER_template::operator=(template_sel other_value
)
2003 check_single_selection(other_value
);
2005 set_selection(other_value
);
2009 INTEGER_template
& INTEGER_template::operator=(int other_value
)
2012 set_selection(SPECIFIC_VALUE
);
2013 int_val
.native_flag
= TRUE
;
2014 int_val
.val
.native
= other_value
;
2018 INTEGER_template
& INTEGER_template::operator=(const INTEGER
& other_value
)
2020 other_value
.must_bound("Assignment of an unbound integer value to a "
2023 set_selection(SPECIFIC_VALUE
);
2024 int_val_t other_value_int
= other_value
.get_val();
2025 int_val
.native_flag
= other_value_int
.native_flag
;
2026 if (likely(int_val
.native_flag
))
2027 int_val
.val
.native
= other_value_int
.val
.native
;
2028 else int_val
.val
.openssl
= BN_dup(other_value_int
.val
.openssl
);
2032 INTEGER_template
& INTEGER_template::operator=
2033 (const OPTIONAL
<INTEGER
>& other_value
)
2036 switch (other_value
.get_selection()) {
2037 case OPTIONAL_PRESENT
: {
2038 set_selection(SPECIFIC_VALUE
);
2039 int_val_t other_value_int
= ((const INTEGER
&)other_value
).get_val();
2040 int_val
.native_flag
= other_value_int
.native_flag
;
2041 if (likely(int_val
.native_flag
))
2042 int_val
.val
.native
= other_value_int
.val
.native
;
2043 else int_val
.val
.openssl
= BN_dup(other_value_int
.val
.openssl
);
2046 set_selection(OMIT_VALUE
);
2049 TTCN_error("Assignment of an unbound optional field to an integer "
2055 INTEGER_template
& INTEGER_template::operator=
2056 (const INTEGER_template
& other_value
)
2058 if (&other_value
!= this) {
2060 copy_template(other_value
);
2065 boolean
INTEGER_template::match(int other_value
, boolean
/* legacy */) const
2067 switch (template_selection
) {
2068 case SPECIFIC_VALUE
:
2069 if (likely(int_val
.native_flag
)) return int_val
.val
.native
== other_value
;
2070 return int_val_t(BN_dup(int_val
.val
.openssl
)) == other_value
;
2077 case COMPLEMENTED_LIST
:
2078 for(unsigned int i
= 0; i
< value_list
.n_values
; i
++)
2079 if (value_list
.list_value
[i
].match(other_value
))
2080 return template_selection
== VALUE_LIST
;
2081 return template_selection
== COMPLEMENTED_LIST
;
2083 boolean lower_boundary
= !value_range
.min_is_present
;
2084 boolean upper_boundary
= !value_range
.max_is_present
;
2085 // Lower boundary is set.
2086 if (!lower_boundary
) {
2087 lower_boundary
= (likely(value_range
.min_value
.native_flag
) ?
2088 int_val_t(value_range
.min_value
.val
.native
) :
2089 int_val_t(BN_dup(value_range
.min_value
.val
.openssl
))) <= other_value
;
2091 // Upper boundary is set.
2092 if (!upper_boundary
) {
2093 upper_boundary
= (likely(value_range
.max_value
.native_flag
) ?
2094 int_val_t(value_range
.max_value
.val
.native
) :
2095 int_val_t(BN_dup(value_range
.max_value
.val
.openssl
))) >= other_value
;
2097 return lower_boundary
&& upper_boundary
; }
2099 TTCN_error("Matching with an uninitialized/unsupported integer "
2105 boolean
INTEGER_template::match(const INTEGER
& other_value
,
2106 boolean
/* legacy */) const
2108 if (!other_value
.is_bound()) return FALSE
;
2109 switch (template_selection
) {
2110 case SPECIFIC_VALUE
: {
2111 int_val_t int_val_int
= likely(int_val
.native_flag
) ?
2112 int_val_t(int_val
.val
.native
) : int_val_t(BN_dup(int_val
.val
.openssl
));
2113 return int_val_int
== other_value
.get_val(); }
2120 case COMPLEMENTED_LIST
: // Merged cases.
2121 for (unsigned int i
= 0; i
< value_list
.n_values
; i
++)
2122 if (value_list
.list_value
[i
].match(other_value
))
2123 return template_selection
== VALUE_LIST
;
2124 return template_selection
== COMPLEMENTED_LIST
;
2126 boolean lower_boundary
= !value_range
.min_is_present
;
2127 boolean upper_boundary
= !value_range
.max_is_present
;
2128 // Lower boundary is set.
2129 if (!lower_boundary
) {
2130 lower_boundary
= (likely(value_range
.min_value
.native_flag
) ?
2131 int_val_t(value_range
.min_value
.val
.native
) :
2132 int_val_t(BN_dup(value_range
.min_value
.val
.openssl
))) <= other_value
.get_val();
2134 // Upper boundary is set.
2135 if (!upper_boundary
) {
2136 upper_boundary
= (likely(value_range
.max_value
.native_flag
) ?
2137 int_val_t(value_range
.max_value
.val
.native
) :
2138 int_val_t(BN_dup(value_range
.max_value
.val
.openssl
))) >= other_value
.get_val();
2140 return lower_boundary
&& upper_boundary
; }
2142 TTCN_error("Matching with an uninitialized/unsupported integer "
2148 INTEGER
INTEGER_template::valueof() const
2150 if (template_selection
!= SPECIFIC_VALUE
|| is_ifpresent
)
2151 TTCN_error("Performing a valueof or send operation on a non-specific "
2152 "integer template.");
2153 if (likely(int_val
.native_flag
)) return INTEGER(int_val
.val
.native
);
2154 else return INTEGER(BN_dup(int_val
.val
.openssl
));
2157 void INTEGER_template::set_type(template_sel template_type
,
2158 unsigned int list_length
)
2161 switch (template_type
) {
2163 case COMPLEMENTED_LIST
:
2164 set_selection(template_type
);
2165 value_list
.n_values
= list_length
;
2166 value_list
.list_value
= new INTEGER_template
[list_length
];
2169 set_selection(VALUE_RANGE
);
2170 value_range
.min_is_present
= FALSE
;
2171 value_range
.max_is_present
= FALSE
;
2174 TTCN_error("Setting an invalid type for an integer template.");
2178 INTEGER_template
& INTEGER_template::list_item(unsigned int list_index
)
2180 if (template_selection
!= VALUE_LIST
&&
2181 template_selection
!= COMPLEMENTED_LIST
)
2182 TTCN_error("Accessing a list element of a non-list integer template.");
2183 if (list_index
>= value_list
.n_values
)
2184 TTCN_error("Index overflow in an integer value list template.");
2185 return value_list
.list_value
[list_index
];
2188 void INTEGER_template::set_min(int min_value
)
2190 if (template_selection
!= VALUE_RANGE
)
2191 TTCN_error("Integer template is not range when setting lower limit.");
2192 if (value_range
.max_is_present
) {
2193 int_val_t max_value_int
= likely(value_range
.max_value
.native_flag
) ?
2194 int_val_t(value_range
.max_value
.val
.native
) :
2195 int_val_t(BN_dup(value_range
.max_value
.val
.openssl
));
2196 if (max_value_int
< min_value
)
2197 TTCN_error("The lower limit of the range is greater than the upper "
2198 "limit in an integer template.");
2200 value_range
.min_is_present
= TRUE
;
2201 value_range
.min_value
.native_flag
= TRUE
;
2202 value_range
.min_value
.val
.native
= min_value
;
2205 void INTEGER_template::set_min(const INTEGER
& min_value
)
2207 // Redundant, but performace matters. :)
2208 min_value
.must_bound("Using an unbound value when setting the lower bound "
2209 "in an integer range template.");
2210 if (template_selection
!= VALUE_RANGE
)
2211 TTCN_error("Integer template is not range when setting lower limit.");
2212 int_val_t min_value_int
= min_value
.get_val();
2213 if (value_range
.max_is_present
) {
2214 int_val_t max_value_int
= likely(value_range
.max_value
.native_flag
) ?
2215 int_val_t(value_range
.max_value
.val
.native
) :
2216 int_val_t(BN_dup(value_range
.max_value
.val
.openssl
));
2217 if (max_value_int
< min_value_int
)
2218 TTCN_error("The lower limit of the range is greater than the upper "
2219 "limit in an integer template.");
2221 value_range
.min_is_present
= TRUE
;
2222 value_range
.min_value
.native_flag
= min_value_int
.native_flag
;
2223 if (likely(value_range
.min_value
.native_flag
))
2224 value_range
.min_value
.val
.native
= min_value_int
.val
.native
;
2225 else value_range
.min_value
.val
.openssl
= BN_dup(min_value_int
.val
.openssl
);
2228 void INTEGER_template::set_max(int max_value
)
2230 if (template_selection
!= VALUE_RANGE
)
2231 TTCN_error("Integer template is not range when setting upper limit.");
2232 if (value_range
.min_is_present
) {
2233 int_val_t min_value_int
= likely(value_range
.min_value
.native_flag
) ?
2234 int_val_t(value_range
.min_value
.val
.native
) :
2235 int_val_t(BN_dup(value_range
.min_value
.val
.openssl
));
2236 if (min_value_int
> max_value
)
2237 TTCN_error("The upper limit of the range is smaller than the lower "
2238 "limit in an integer template.");
2240 value_range
.max_is_present
= TRUE
;
2241 value_range
.max_value
.native_flag
= TRUE
;
2242 value_range
.max_value
.val
.native
= max_value
;
2245 void INTEGER_template::set_max(const INTEGER
& max_value
)
2247 max_value
.must_bound("Using an unbound value when setting the upper bound "
2248 "in an integer range template.");
2249 if (template_selection
!= VALUE_RANGE
)
2250 TTCN_error("Integer template is not range when setting upper limit.");
2251 int_val_t max_value_int
= max_value
.get_val();
2252 if (value_range
.min_is_present
) {
2253 int_val_t min_value_int
= likely(value_range
.min_value
.native_flag
) ?
2254 int_val_t(value_range
.min_value
.val
.native
) :
2255 int_val_t(BN_dup(value_range
.min_value
.val
.openssl
));
2256 if (min_value_int
> max_value_int
)
2257 TTCN_error("The upper limit of the range is smaller than the lower "
2258 "limit in an integer template.");
2260 value_range
.max_is_present
= TRUE
;
2261 value_range
.max_value
.native_flag
= max_value_int
.native_flag
;
2262 if (likely(value_range
.max_value
.native_flag
))
2263 value_range
.max_value
.val
.native
= max_value_int
.val
.native
;
2264 else value_range
.max_value
.val
.openssl
= BN_dup(max_value_int
.val
.openssl
);
2267 void INTEGER_template::log() const
2269 switch (template_selection
) {
2270 case SPECIFIC_VALUE
: {
2271 int_val_t int_val_int
= likely(int_val
.native_flag
) ?
2272 int_val_t(int_val
.val
.native
) : int_val_t(BN_dup(int_val
.val
.openssl
));
2273 char *tmp_str
= int_val_int
.as_string();
2274 TTCN_Logger::log_event("%s", tmp_str
);
2277 case COMPLEMENTED_LIST
:
2278 TTCN_Logger::log_event_str("complement ");
2281 TTCN_Logger::log_char('(');
2282 for (unsigned int i
= 0; i
< value_list
.n_values
; i
++) {
2283 if (i
> 0) TTCN_Logger::log_event_str(", ");
2284 value_list
.list_value
[i
].log();
2286 TTCN_Logger::log_char(')');
2289 TTCN_Logger::log_char('(');
2290 if (value_range
.min_is_present
) {
2291 int_val_t min_value_int
= likely(value_range
.min_value
.native_flag
) ?
2292 int_val_t(value_range
.min_value
.val
.native
) :
2293 int_val_t(BN_dup(value_range
.min_value
.val
.openssl
));
2294 char *min_str
= min_value_int
.as_string();
2295 TTCN_Logger::log_event("%s", min_str
);
2298 TTCN_Logger::log_event_str("-infinity");
2300 TTCN_Logger::log_event_str(" .. ");
2301 if (value_range
.max_is_present
) {
2302 int_val_t max_value_int
= likely(value_range
.max_value
.native_flag
) ?
2303 int_val_t(value_range
.max_value
.val
.native
) :
2304 int_val_t(BN_dup(value_range
.max_value
.val
.openssl
));
2305 char *max_str
= max_value_int
.as_string();
2306 TTCN_Logger::log_event("%s", max_str
);
2309 TTCN_Logger::log_event_str("infinity");
2311 TTCN_Logger::log_char(')');
2320 void INTEGER_template::log_match(const INTEGER
& match_value
,
2321 boolean
/* legacy */) const
2323 if (TTCN_Logger::VERBOSITY_COMPACT
== TTCN_Logger::get_matching_verbosity()
2324 && TTCN_Logger::get_logmatch_buffer_len() != 0) {
2325 TTCN_Logger::print_logmatch_buffer();
2326 TTCN_Logger::log_event_str(" := ");
2329 TTCN_Logger::log_event_str(" with ");
2331 if (match(match_value
)) TTCN_Logger::log_event_str(" matched");
2332 else TTCN_Logger::log_event_str(" unmatched");
2335 void INTEGER_template::set_param(Module_Param
& param
) {
2336 param
.basic_check(Module_Param::BC_TEMPLATE
, "integer template");
2337 Module_Param_Ptr mp
= ¶m
;
2338 if (param
.get_type() == Module_Param::MP_Reference
) {
2339 mp
= param
.get_referenced_param();
2341 switch (mp
->get_type()) {
2342 case Module_Param::MP_Omit
:
2345 case Module_Param::MP_Any
:
2348 case Module_Param::MP_AnyOrNone
:
2349 *this = ANY_OR_OMIT
;
2351 case Module_Param::MP_List_Template
:
2352 case Module_Param::MP_ComplementList_Template
: {
2353 INTEGER_template temp
;
2354 temp
.set_type(mp
->get_type() == Module_Param::MP_List_Template
?
2355 VALUE_LIST
: COMPLEMENTED_LIST
, mp
->get_size());
2356 for (size_t i
=0; i
<mp
->get_size(); i
++) {
2357 temp
.list_item(i
).set_param(*mp
->get_elem(i
));
2361 case Module_Param::MP_Integer
: {
2363 tmp
.set_val(*mp
->get_integer());
2366 case Module_Param::MP_IntRange
: {
2367 set_type(VALUE_RANGE
);
2368 if (mp
->get_lower_int()!=NULL
) {
2370 tmp
.set_val(*mp
->get_lower_int());
2373 if (mp
->get_upper_int()!=NULL
) {
2375 tmp
.set_val(*mp
->get_upper_int());
2379 case Module_Param::MP_Expression
:
2380 switch (mp
->get_expr_type()) {
2381 case Module_Param::EXPR_NEGATE
: {
2383 operand
.set_param(*mp
->get_operand1());
2386 case Module_Param::EXPR_ADD
: {
2387 INTEGER operand1
, operand2
;
2388 operand1
.set_param(*mp
->get_operand1());
2389 operand2
.set_param(*mp
->get_operand2());
2390 *this = operand1
+ operand2
;
2392 case Module_Param::EXPR_SUBTRACT
: {
2393 INTEGER operand1
, operand2
;
2394 operand1
.set_param(*mp
->get_operand1());
2395 operand2
.set_param(*mp
->get_operand2());
2396 *this = operand1
- operand2
;
2398 case Module_Param::EXPR_MULTIPLY
: {
2399 INTEGER operand1
, operand2
;
2400 operand1
.set_param(*mp
->get_operand1());
2401 operand2
.set_param(*mp
->get_operand2());
2402 *this = operand1
* operand2
;
2404 case Module_Param::EXPR_DIVIDE
: {
2405 INTEGER operand1
, operand2
;
2406 operand1
.set_param(*mp
->get_operand1());
2407 operand2
.set_param(*mp
->get_operand2());
2408 if (operand2
== 0) {
2409 param
.error("Integer division by zero.");
2411 *this = operand1
/ operand2
;
2414 param
.expr_type_error("an integer");
2419 param
.type_error("integer template");
2421 is_ifpresent
= param
.get_ifpresent() || mp
->get_ifpresent();
2424 Module_Param
* INTEGER_template::get_param(Module_Param_Name
& param_name
) const
2426 Module_Param
* mp
= NULL
;
2427 switch (template_selection
) {
2428 case UNINITIALIZED_TEMPLATE
:
2429 mp
= new Module_Param_Unbound();
2432 mp
= new Module_Param_Omit();
2435 mp
= new Module_Param_Any();
2438 mp
= new Module_Param_AnyOrNone();
2440 case SPECIFIC_VALUE
:
2441 if (likely(int_val
.native_flag
)) {
2442 mp
= new Module_Param_Integer(new int_val_t(int_val
.val
.native
));
2445 mp
= new Module_Param_Integer(new int_val_t(BN_dup(int_val
.val
.openssl
)));
2449 case COMPLEMENTED_LIST
: {
2450 if (template_selection
== VALUE_LIST
) {
2451 mp
= new Module_Param_List_Template();
2454 mp
= new Module_Param_ComplementList_Template();
2456 for (size_t i
= 0; i
< value_list
.n_values
; ++i
) {
2457 mp
->add_elem(value_list
.list_value
[i
].get_param(param_name
));
2461 int_val_t
* lower_bound
= NULL
;
2462 int_val_t
* upper_bound
= NULL
;
2463 if (value_range
.min_is_present
) {
2464 if (value_range
.min_value
.native_flag
) {
2465 lower_bound
= new int_val_t(value_range
.min_value
.val
.native
);
2468 lower_bound
= new int_val_t(BN_dup(value_range
.min_value
.val
.openssl
));
2471 if (value_range
.max_is_present
) {
2472 if (value_range
.max_value
.native_flag
) {
2473 upper_bound
= new int_val_t(value_range
.max_value
.val
.native
);
2476 upper_bound
= new int_val_t(BN_dup(value_range
.max_value
.val
.openssl
));
2479 mp
= new Module_Param_IntRange(lower_bound
, upper_bound
);
2485 mp
->set_ifpresent();
2490 void INTEGER_template::encode_text(Text_Buf
& text_buf
) const
2492 encode_text_base(text_buf
);
2493 switch (template_selection
) {
2498 case SPECIFIC_VALUE
:
2499 text_buf
.push_int(likely(int_val
.native_flag
) ? int_val_t(int_val
.val
.native
)
2500 : int_val_t(BN_dup(int_val
.val
.openssl
)));
2503 case COMPLEMENTED_LIST
:
2504 text_buf
.push_int(value_list
.n_values
);
2505 for (unsigned int i
= 0; i
< value_list
.n_values
; i
++)
2506 value_list
.list_value
[i
].encode_text(text_buf
);
2509 text_buf
.push_int(value_range
.min_is_present
? 1 : 0);
2510 if (value_range
.min_is_present
)
2511 text_buf
.push_int(likely(value_range
.min_value
.native_flag
) ?
2512 int_val_t(value_range
.min_value
.val
.native
) :
2513 int_val_t(BN_dup(value_range
.min_value
.val
.openssl
)));
2514 text_buf
.push_int(value_range
.max_is_present
? 1 : 0);
2515 if (value_range
.max_is_present
)
2516 text_buf
.push_int(likely(value_range
.max_value
.native_flag
) ?
2517 int_val_t(value_range
.max_value
.val
.native
) :
2518 int_val_t(BN_dup(value_range
.max_value
.val
.openssl
)));
2521 TTCN_error("Text encoder: Encoding an uninitialized/unsupported integer "
2526 void INTEGER_template::decode_text(Text_Buf
& text_buf
)
2529 decode_text_base(text_buf
);
2530 switch (template_selection
) {
2535 case SPECIFIC_VALUE
: {
2536 int_val_t int_val_int
= text_buf
.pull_int();
2537 int_val
.native_flag
= int_val_int
.native_flag
;
2538 if (likely(int_val
.native_flag
)) int_val
.val
.native
= int_val_int
.val
.native
;
2539 else int_val
.val
.openssl
= BN_dup(int_val_int
.val
.openssl
);
2542 case COMPLEMENTED_LIST
:
2543 value_list
.n_values
= text_buf
.pull_int().get_val();
2544 value_list
.list_value
= new INTEGER_template
[value_list
.n_values
];
2545 for (unsigned int i
= 0; i
< value_list
.n_values
; i
++)
2546 value_list
.list_value
[i
].decode_text(text_buf
);
2549 value_range
.min_is_present
= text_buf
.pull_int() != 0;
2550 if (value_range
.min_is_present
) {
2551 int_val_t min_value_int
= text_buf
.pull_int();
2552 value_range
.min_value
.native_flag
= min_value_int
.native_flag
;
2553 if (likely(value_range
.min_value
.native_flag
))
2554 value_range
.min_value
.val
.native
= min_value_int
.val
.native
;
2555 else value_range
.min_value
.val
.openssl
= BN_dup(min_value_int
.val
.openssl
);
2557 value_range
.max_is_present
= text_buf
.pull_int() != 0;
2558 if (value_range
.max_is_present
) {
2559 int_val_t max_value_int
= text_buf
.pull_int();
2560 value_range
.max_value
.native_flag
= max_value_int
.native_flag
;
2561 if (likely(value_range
.max_value
.native_flag
))
2562 value_range
.max_value
.val
.native
= max_value_int
.val
.native
;
2563 else value_range
.max_value
.val
.openssl
= BN_dup(max_value_int
.val
.openssl
);
2567 TTCN_error("Text decoder: An unknown/unsupported selection was received "
2568 "for an integer template.");
2572 boolean
INTEGER_template::is_present(boolean legacy
/* = FALSE */) const
2574 if (template_selection
==UNINITIALIZED_TEMPLATE
) return FALSE
;
2575 return !match_omit(legacy
);
2578 boolean
INTEGER_template::match_omit(boolean legacy
/* = FALSE */) const
2580 if (is_ifpresent
) return TRUE
;
2581 switch (template_selection
) {
2586 case COMPLEMENTED_LIST
:
2588 // legacy behavior: 'omit' can appear in the value/complement list
2589 for (unsigned int i
=0; i
<value_list
.n_values
; i
++)
2590 if (value_list
.list_value
[i
].match_omit())
2591 return template_selection
==VALUE_LIST
;
2592 return template_selection
==COMPLEMENTED_LIST
;
2594 // else fall through
2601 #ifndef TITAN_RUNTIME_2
2602 void INTEGER_template::check_restriction(template_res t_res
, const char* t_name
,
2603 boolean legacy
/* = FALSE */) const
2605 if (template_selection
==UNINITIALIZED_TEMPLATE
) return;
2606 switch ((t_name
&&(t_res
==TR_VALUE
))?TR_OMIT
:t_res
) {
2608 if (!is_ifpresent
&& template_selection
==SPECIFIC_VALUE
) return;
2611 if (!is_ifpresent
&& (template_selection
==OMIT_VALUE
||
2612 template_selection
==SPECIFIC_VALUE
)) return;
2615 if (!match_omit(legacy
)) return;
2620 TTCN_error("Restriction `%s' on template of type %s violated.",
2621 get_res_name(t_res
), t_name
? t_name
: "integer");