debugger: added help in single mode UI, plus minor fixes
[deliverable/titan.core.git] / core / Integer.cc
CommitLineData
d44e3c4f 1/******************************************************************************
2 * Copyright (c) 2000-2016 Ericsson Telecom AB
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/epl-v10.html
7 *
8 * Contributors:
9 * Baji, Laszlo
10 * Balasko, Jeno
11 * Baranyi, Botond
12 * Beres, Szabolcs
13 * Delic, Adam
14 * Forstner, Matyas
15 * Kovacs, Ferenc
16 * Ormandi, Matyas
17 * Raduly, Csaba
18 * Szabados, Kristof
19 * Szabo, Bence Janos
20 * Szabo, Janos Zoltan – initial implementation
21 * Szalai, Gabor
22 * Tatarka, Gabor
23 *
24 ******************************************************************************/
970ed795
EL
25#include "Integer.hh"
26
27#include <limits.h>
28#include <strings.h>
29#include <string.h>
30#include <ctype.h>
31
32#include "Error.hh"
33#include "Logger.hh"
34#include "Optional.hh"
35#include "Types.h"
36#include "Param_Types.hh"
37#include "Encdec.hh"
38#include "RAW.hh"
39#include "BER.hh"
40#include "TEXT.hh"
41#include "Charstring.hh"
42#include "Addfunc.hh"
43#include "XmlReader.hh"
44
45#include <openssl/bn.h>
46#include <openssl/crypto.h>
47
48#include "../common/dbgnew.hh"
49
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)
55#else
56#define likely(x) (x)
57#define unlikely(x) (x)
58#endif
59
60static const Token_Match integer_value_match("^([\t ]*-?[0-9]+).*$", TRUE);
61
62int_val_t INTEGER::get_val() const
63{
64 if (likely(native_flag)) return int_val_t(val.native);
65 else return int_val_t(BN_dup(val.openssl));
66}
67
68void INTEGER::set_val(const int_val_t& other_value)
69{
70 clean_up();
71 bound_flag = TRUE;
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);
75}
76
77INTEGER::INTEGER()
78{
79 bound_flag = FALSE;
80 native_flag = TRUE;
81}
82
83INTEGER::INTEGER(int other_value)
84{
85 bound_flag = TRUE;
86 native_flag = TRUE;
87 val.native = other_value;
88}
89
90INTEGER::INTEGER(const INTEGER& other_value)
91: Base_Type(other_value)
92{
93 other_value.must_bound("Copying an unbound integer value.");
94 bound_flag = TRUE;
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);
98}
99
100/// Return 0 if fail, 1 on success
101int INTEGER::from_string(const char *s) {
102 BIGNUM *other_value_int = NULL;
103 if (BN_dec2bn(&other_value_int, s + (*s == '+')))
104 {
105 bound_flag = TRUE;
106 if (BN_num_bits(other_value_int) > (int)sizeof(int) * 8 - 1) {
107 native_flag = FALSE;
108 val.openssl = other_value_int;
109 } else {
110 native_flag = TRUE;
111 val.native = string2RInt(s);
112 BN_free(other_value_int);
113 }
114 return 1;
115 }
116 else return 0;
117}
118
119INTEGER::INTEGER(const char *other_value)
120{
121 if (unlikely(!other_value))
122 TTCN_error("Unexpected error when converting `%s' to integer",
123 other_value);
124 bound_flag = TRUE;
125 if (!from_string(other_value)) TTCN_error(
126 "Unexpected error when converting `%s' to integer", other_value);
127}
128
129// For internal use only. It's not part of the public interface.
130INTEGER::INTEGER(BIGNUM *other_value)
131{
132 if (unlikely(!other_value))
133 TTCN_error("Unexpected error when initializing an integer");
134 bound_flag = TRUE;
135 native_flag = FALSE;
136 val.openssl = other_value;
137}
138
139INTEGER::~INTEGER()
140{
51fa56b9 141 if (!bound_flag) return;
970ed795
EL
142 if (unlikely(!native_flag)) BN_free(val.openssl);
143}
144
145void INTEGER::clean_up()
146{
147 if (!bound_flag) return;
148 if (unlikely(!native_flag)) BN_free(val.openssl);
149 bound_flag = FALSE;
150}
151
152INTEGER& INTEGER::operator=(int other_value)
153{
154 clean_up();
155 bound_flag = TRUE;
156 native_flag = TRUE;
157 val.native = other_value;
158 return *this;
159}
160
161INTEGER& INTEGER::operator=(const INTEGER& other_value)
162{
163 if (this == &other_value)
164 return *this;
165 other_value.must_bound("Assignment of an unbound integer value.");
166 clean_up();
167 bound_flag = TRUE;
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);
171 return *this;
172}
173
174// A bit more specific than operator+().
175INTEGER& INTEGER::operator++()
176{
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();
184 BN_set_word(one, 1);
185 BN_add(val_openssl, val_openssl, one);
186 BN_free(one);
187 native_flag = FALSE;
188 val.openssl = val_openssl;
189 } else {
190 val.native++;
191 }
192 } else {
193 BIGNUM *one = BN_new();
194 BN_set_word(one, 1);
195 BN_add(val.openssl, val.openssl, one);
196 BN_free(one);
197 }
198 return *this;
199}
200
201// A bit more specific than operator-().
202INTEGER& INTEGER::operator--()
203{
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();
209 BN_set_word(one, 1);
210 BN_sub(val_openssl, val_openssl, one);
211 BN_free(one);
212 native_flag = FALSE;
213 val.openssl = val_openssl;
214 } else {
215 val.native--;
216 }
217 } else {
218 BIGNUM *one = BN_new();
219 BN_set_word(one, 1);
220 BN_sub(val.openssl, val.openssl, one);
221 BN_free(one);
222 }
223 return *this;
224}
225
226INTEGER INTEGER::operator+() const
227{
228 must_bound("Unbound integer operand of unary + operator.");
229 return *this;
230}
231
232INTEGER INTEGER::operator-() const
233{
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);
240 } else {
241 return INTEGER(-val.native);
242 }
243 } else {
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);
250 } else {
251 BIGNUM *result = BN_dup(val.openssl);
252 BN_set_negative(result, !BN_is_negative(result));
253 return INTEGER(result);
254 }
255 }
256}
257
258INTEGER INTEGER::operator+(int other_value) const
259{
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);
263}
264
265INTEGER INTEGER::operator+(const INTEGER& other_value) const
266{
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
274 // the beginning.
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);
297 } else {
298 return INTEGER(result);
299 }
300 } else {
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);
305 }
306 } else {
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);
315 }
316}
317
318INTEGER INTEGER::operator-(int other_value) const
319{
320 must_bound("Unbound left operand of integer subtraction.");
321 return *this - INTEGER(other_value);
322}
323
324INTEGER INTEGER::operator-(const INTEGER& other_value) const
325{
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);
344 } else {
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);
353 BN_free(this_int);
354 return INTEGER(result);
355 } else {
356 return INTEGER(this_int);
357 }
358 }
359 } else {
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);
369 BN_free(result);
370 return INTEGER(result_int);
371 } else {
372 return INTEGER(result);
373 }
374 }
375}
376
377INTEGER INTEGER::operator*(int other_value) const
378{
379 must_bound("Unbound left operand of integer multiplication.");
380 return *this * INTEGER(other_value);
381}
382
383INTEGER INTEGER::operator*(const INTEGER& other_value) const
384{
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)) {
391 // TODO: Improve.
392 if (likely(abs(val.native) < 32768 && abs(other_value.val.native) < 32768)) {
393 return INTEGER(val.native * other_value.val.native);
394 } else {
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();
398 BN_CTX_init(ctx);
399 BN_mul(this_int, this_int, other_value_int, ctx);
400 BN_CTX_free(ctx);
401 BN_free(other_value_int);
402 if (BN_num_bits(this_int) < (int)sizeof(int) * 8) {
403 BN_free(this_int);
404 return INTEGER(val.native * other_value.val.native);
405 } else {
406 return INTEGER(this_int);
407 }
408 }
409 } else {
410 BIGNUM *this_int = to_openssl(val.native);
411 BN_CTX *ctx = BN_CTX_new();
412 BN_CTX_init(ctx);
413 BN_mul(this_int, this_int, other_value.val.openssl, ctx);
414 BN_CTX_free(ctx);
415 return INTEGER(this_int);
416 }
417 } else {
418 BIGNUM *result = BN_new();
419 BIGNUM *other_value_int = NULL;
420 BN_CTX *ctx = BN_CTX_new();
421 BN_CTX_init(ctx);
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);
425 BN_CTX_free(ctx);
426 if (likely(other_value.native_flag)) BN_free(other_value_int);
427 return INTEGER(result);
428 }
429}
430
431INTEGER INTEGER::operator/(int other_value) const
432{
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);
436}
437
438INTEGER INTEGER::operator/(const INTEGER& other_value) const
439{
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);
447 } else {
448 BIGNUM *this_int = to_openssl(val.native);
449 BN_CTX *ctx = BN_CTX_new();
450 BN_CTX_init(ctx);
451 BN_div(this_int, NULL, this_int, other_value.val.openssl, ctx);
452 BN_CTX_free(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);
457 BN_free(this_int);
458 return INTEGER(result);
459 } else {
460 return INTEGER(this_int);
461 }
462 }
463 } else {
464 BIGNUM *result = BN_new();
465 BIGNUM *other_value_int = NULL;
466 BN_CTX *ctx = BN_CTX_new();
467 BN_CTX_init(ctx);
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);
472 BN_CTX_free(ctx);
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);
477 BN_free(result);
478 return INTEGER(result_i);
479 } else {
480 return INTEGER(result);
481 }
482 }
483}
484
485boolean INTEGER::operator==(int other_value) const
486{
487 must_bound("Unbound left operand of integer comparison.");
488 if (likely(native_flag)) {
489 return val.native == other_value;
490 } else {
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);
494 return equal == 0;
495 }
496}
497
498boolean INTEGER::operator==(const INTEGER& other_value) const
499{
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;
505 } else {
506 BIGNUM *this_int = to_openssl(val.native);
507 int equal = BN_cmp(this_int, other_value.val.openssl);
508 BN_free(this_int);
509 return equal == 0;
510 }
511 } else {
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);
516 return equal == 0;
517 } else {
518 return BN_cmp(val.openssl, other_value.val.openssl) == 0;
519 }
520 }
521}
522
523boolean INTEGER::operator<(int other_value) const
524{
525 must_bound("Unbound left operand of integer comparison.");
526 return *this < INTEGER(other_value);
527}
528
529boolean INTEGER::operator<(const INTEGER& other_value) const
530{
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;
536 } else {
537 BIGNUM *this_int = to_openssl(val.native);
538 int equal = BN_cmp(this_int, other_value.val.openssl);
539 BN_free(this_int);
540 return equal == -1;
541 }
542 } else {
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);
547 return equal == -1;
548 } else {
549 return BN_cmp(val.openssl, other_value.val.openssl) == -1;
550 }
551 }
552}
553
554boolean INTEGER::operator>(int other_value) const
555{
556 must_bound("Unbound left operand of integer comparison.");
557 return *this > INTEGER(other_value);
558}
559
560boolean INTEGER::operator>(const INTEGER& other_value) const
561{
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;
568 } else {
569 BIGNUM *this_int = to_openssl(val.native);
570 int equal = BN_cmp(this_int, other_value.val.openssl);
571 BN_free(this_int);
572 return equal == 1;
573 }
574 } else {
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);
579 return equal == 1;
580 } else {
581 return BN_cmp(val.openssl, other_value.val.openssl) == 1;
582 }
583 }
584}
585
586INTEGER::operator int() const
587{
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");
591 return val.native;
592}
593
594// To avoid ambiguity we have a separate function to convert our INTEGER
595// object to long long.
596long long int INTEGER::get_long_long_val() const
597{
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
605 // conversion...
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;
613 ret_val <<= 8;
614 ret_val += tmp;
615 }
616 }
617 return !is_negative ? ret_val : -ret_val;
618}
619
620void INTEGER::set_long_long_val(long long int other_value)
621{
622 clean_up();
623 bound_flag = TRUE;
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)) {
627 native_flag = TRUE;
628 val.native = other_value;
629 return;
630 }
631 native_flag = FALSE;
632 val.openssl = BN_new();
633 // Make it 0.
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);
640 }
641 BN_set_negative(val.openssl, is_negative ? 1 : 0);
642}
643
644void INTEGER::log() const
645{
646 if (likely(bound_flag)) {
647 if (likely(native_flag)) {
648 TTCN_Logger::log_event("%d", val.native);
649 } else {
650 char *tmp = BN_bn2dec(val.openssl);
651 TTCN_Logger::log_event("%s", tmp);
652 OPENSSL_free(tmp);
653 }
654 } else {
655 TTCN_Logger::log_event_unbound();
656 }
657}
658
659void INTEGER::set_param(Module_Param& param)
660{
661 param.basic_check(Module_Param::BC_VALUE, "integer value");
3abe9331 662 Module_Param_Ptr mp = &param;
663 if (param.get_type() == Module_Param::MP_Reference) {
664 mp = param.get_referenced_param();
665 }
666 switch (mp->get_type()) {
667 case Module_Param::MP_Integer: {
668 clean_up();
669 bound_flag = TRUE;
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();
674 } else {
675 val.openssl = BN_dup(int_val->get_val_openssl());
676 }
677 break; }
678 case Module_Param::MP_Expression:
679 switch (mp->get_expr_type()) {
680 case Module_Param::EXPR_NEGATE: {
681 INTEGER operand;
682 operand.set_param(*mp->get_operand1());
683 *this = - operand;
684 break; }
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;
690 break; }
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;
696 break; }
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;
702 break; }
703 case Module_Param::EXPR_DIVIDE: {
704 INTEGER operand1, operand2;
705 operand1.set_param(*mp->get_operand1());
706 operand2.set_param(*mp->get_operand2());
707 if (operand2 == 0) {
708 param.error("Integer division by zero.");
709 }
710 *this = operand1 / operand2;
711 break; }
712 default:
713 param.expr_type_error("an integer");
714 break;
715 }
716 break;
717 default:
718 param.type_error("integer value");
719 break;
970ed795
EL
720 }
721}
722
3abe9331 723Module_Param* INTEGER::get_param(Module_Param_Name& /* param_name */) const
724{
725 if (!bound_flag) {
726 return new Module_Param_Unbound();
727 }
728 if (native_flag) {
729 return new Module_Param_Integer(new int_val_t(val.native));
730 }
731 return new Module_Param_Integer(new int_val_t(BN_dup(val.openssl)));
732}
733
970ed795
EL
734void INTEGER::encode_text(Text_Buf& text_buf) const
735{
736 must_bound("Text encoder: Encoding an unbound integer value.");
737 if (likely(native_flag)) {
738 text_buf.push_int(val.native);
739 } else {
740 int_val_t *tmp = new int_val_t(BN_dup(val.openssl));
741 text_buf.push_int(*tmp);
742 delete tmp;
743 }
744}
745
746void INTEGER::decode_text(Text_Buf& text_buf)
747{
748 clean_up();
749 bound_flag = TRUE;
750 int_val_t tmp(text_buf.pull_int());
751 if (likely(tmp.native_flag)) {
752 native_flag = TRUE;
753 val.native = tmp.get_val();
754 } else {
755 native_flag = FALSE;
756 val.openssl = BN_dup(tmp.get_val_openssl());
757 }
758}
759
760void INTEGER::encode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf,
761 TTCN_EncDec::coding_t p_coding, ...) const
762{
763 va_list pvar;
764 va_start(pvar, p_coding);
765 switch(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);
773 break;}
774 case TTCN_EncDec::CT_RAW: {
775 TTCN_EncDec_ErrorContext ec("While RAW-encoding type '%s': ", p_td.name);
776 if(!p_td.raw)
777 TTCN_EncDec_ErrorContext::error_internal
778 ("No RAW descriptor available for type '%s'.", p_td.name);
779 RAW_enc_tr_pos rp;
780 rp.level=0;
781 rp.pos=NULL;
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);
785 break;}
786 case TTCN_EncDec::CT_TEXT: {
787 TTCN_EncDec_ErrorContext ec("While TEXT-encoding type '%s': ", p_td.name);
788 if(!p_td.text)
789 TTCN_EncDec_ErrorContext::error_internal
790 ("No TEXT descriptor available for type '%s'.", p_td.name);
791 TEXT_encode(p_td,p_buf);
792 break;}
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);
af710487 796 XER_encode(*p_td.xer, p_buf, XER_coding, 0, 0);
970ed795
EL
797 break;}
798 case TTCN_EncDec::CT_JSON: {
799 TTCN_EncDec_ErrorContext ec("While JSON-encoding type '%s': ", p_td.name);
800 if(!p_td.json)
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());
806 break;}
807 default:
808 TTCN_error("Unknown coding method requested to encode type '%s'",
809 p_td.name);
810 }
811 va_end(pvar);
812}
813
814void INTEGER::decode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf,
815 TTCN_EncDec::coding_t p_coding, ...)
816{
817 va_list pvar;
818 va_start(pvar, p_coding);
819 switch(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);
823 ASN_BER_TLV_t tlv;
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());
827 break;}
828 case TTCN_EncDec::CT_RAW: {
829 TTCN_EncDec_ErrorContext ec("While RAW-decoding type '%s': ", p_td.name);
830 if(!p_td.raw)
831 TTCN_EncDec_ErrorContext::error_internal
832 ("No RAW descriptor available for type '%s'.", p_td.name);
833 raw_order_t order;
834 switch(p_td.raw->top_bit_order){
835 case TOP_BIT_LEFT:
836 order=ORDER_LSB;
837 break;
838 case TOP_BIT_RIGHT:
839 default:
840 order=ORDER_MSB;
841 }
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"
846 , p_td.name);
847 break;}
848 case TTCN_EncDec::CT_TEXT: {
849 Limit_Token_List limit;
850 TTCN_EncDec_ErrorContext ec("While TEXT-decoding type '%s': ", p_td.name);
851 if(!p_td.text)
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);
858 p_buf.rewind();
859 }
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"
864 , p_td.name);
865 break;}
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)
873 break;
874 }
feade998 875 XER_decode(*p_td.xer, reader, XER_coding, XER_NONE, 0);
970ed795
EL
876 size_t bytes = reader.ByteConsumed();
877 p_buf.set_pos(bytes);
878 break;}
879 case TTCN_EncDec::CT_JSON: {
880 TTCN_EncDec_ErrorContext ec("While JSON-decoding type '%s': ", p_td.name);
881 if(!p_td.json)
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"
889 , p_td.name);
890 p_buf.set_pos(tok.get_buf_pos());
891 break;}
892 default:
893 TTCN_error("Unknown coding method requested to decode type '%s'",
894 p_td.name);
895 }
896 va_end(pvar);
897}
898
899ASN_BER_TLV_t *INTEGER::BER_encode_TLV(const TTCN_Typedescriptor_t& p_td,
900 unsigned p_coding) const
901{
902 BER_chk_descr(p_td);
903 ASN_BER_TLV_t *new_tlv = BER_encode_chk_bound(is_bound());
904 if (!new_tlv) {
905 if (native_flag) {
906 new_tlv = BER_encode_TLV_INTEGER(p_coding, val.native);
907 } else {
908 // Temporary.
909 int_val_t *tmp = new int_val_t(BN_dup(val.openssl));
910 new_tlv = BER_encode_TLV_INTEGER(p_coding, *tmp);
911 delete tmp;
912 }
913 }
914 new_tlv = ASN_BER_V2TLV(new_tlv, p_td, p_coding);
915 return new_tlv;
916}
917
918boolean INTEGER::BER_decode_TLV(const TTCN_Typedescriptor_t& p_td,
919 const ASN_BER_TLV_t& p_tlv,
920 unsigned L_form)
921{
922 clean_up();
923 bound_flag = FALSE;
924 BER_chk_descr(p_td);
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: ");
928 int_val_t tmp;
929 boolean ret_val = BER_decode_TLV_INTEGER(stripped_tlv, L_form, tmp);
930 if (tmp.is_native()) {
931 native_flag = TRUE;
932 val.native = tmp.get_val();
933 } else {
934 native_flag = FALSE;
935 val.openssl = BN_dup(tmp.get_val_openssl());
936 }
937 if (ret_val) bound_flag = TRUE;
938 return ret_val;
939}
940
941int INTEGER::TEXT_decode(const TTCN_Typedescriptor_t& p_td,
942 TTCN_Buffer& buff, Limit_Token_List& limit, boolean no_err, boolean /*first_call*/)
943{
944 int decoded_length = 0;
945 int str_len = 0;
946 if (p_td.text->begin_decode) {
947 int tl;
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);
953 return 0;
954 }
955 decoded_length += tl;
956 buff.increase_pos(tl);
957 }
958 if (buff.get_read_len() <= 1 && no_err) return -TTCN_EncDec::ET_LEN_ERR;
959 if (p_td.text->select_token) {
960 int tl;
961 if ((tl = p_td.text->select_token->match_begin(buff)) < 0) {
962 if (no_err) return -1;
963 else tl = 0;
964 }
965 str_len = tl;
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) {
970 int tl;
971 if ((tl = p_td.text->end_decode->match_first(buff)) < 0) {
972 if (no_err) return -1;
973 else tl = 0;
974 }
975 str_len = tl;
976 } else if (limit.has_token()) {
977 int tl;
978 if ((tl = limit.match(buff)) < 0) {
979 if (no_err) return -1;
980 else tl = 0;
981 }
982 str_len = tl;
983 } else {
984 int tl;
985 if ((tl = integer_value_match.match_begin(buff)) < 0) {
986 if (no_err) return -1;
987 else tl = 0;
988 }
989 str_len = tl;
990 }
991 boolean err = FALSE;
992 if (str_len > 0) {
993 int offs = 0;
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);
997 atm[str_len] = 0;
998 // 0x2d ('-')
999 // 0x20 (' ')
1000 // 0x30 ('0')
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.
1005 offs -= neg;
1006 } else {
1007 for(; atm[offs] == 0x20; offs++) ;
1008 }
1009 clean_up();
1010 if (0 == strlen(atm + offs) || 0 == from_string(atm+offs)) {
1011 err = TRUE;
1012 native_flag = TRUE;
1013 val.native = 0;
1014 }
1015 Free(atm);
1016 buff.increase_pos(str_len);
1017 decoded_length += str_len;
1018 } else {
1019 err = TRUE;
1020 }
1021 if (err) {
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);
1025 }
1026 if (p_td.text->end_decode) {
1027 int tl;
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);
1033 return 0;
1034 }
1035 decoded_length += tl;
1036 buff.increase_pos(tl);
1037 }
1038 bound_flag = TRUE;
1039 return decoded_length;
1040}
1041
1042int INTEGER::TEXT_encode(const TTCN_Typedescriptor_t& p_td,
1043 TTCN_Buffer& buff) const
1044{
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();
1049 }
1050 if (!is_bound()) {
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();
1056 }
1057 return encoded_length;
1058 }
1059 char *tmp_str;
1060 // Temporary.
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) {
1067 buff.put_cs(ch);
1068 encoded_length += ch.lengthof();
1069 } else {
1070 TTCN_TEXTdescriptor_values params = p_td.text->val.parameters
1071 ->coding_params;
1072 if (params.min_length < 0) {
1073 buff.put_cs(ch);
1074 encoded_length += ch.lengthof();
1075 } else {
1076 unsigned char *p = NULL;
1077 int a = 0;
1078 size_t len = params.min_length + 1;
1079 buff.get_end(p, len);
1080 if (params.leading_zero) {
1081 if (native_flag) {
1082 a = snprintf((char*)p, len, "%0*d", params.min_length, val.native);
1083 } else {
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;
1088 // `sprintf' style.
1089 if (neg) *p = 0x2d;
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;
1094 }
1095 } else {
1096 a = snprintf((char*)p, len, "%*s", p_td.text->val.parameters->
1097 coding_params.min_length, (const char*)ch);
1098 }
1099 buff.increase_length(a);
1100 encoded_length += a;
1101 }
1102 }
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();
1106 }
1107 return encoded_length;
1108}
1109
3abe9331 1110unsigned char INTX_MASKS[] = { 0 /*dummy*/, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF };
1111
970ed795
EL
1112int INTEGER::RAW_encode(const TTCN_Typedescriptor_t& p_td, RAW_enc_tree& myleaf) const
1113{
1114 if (!native_flag) return RAW_encode_openssl(p_td, myleaf);
1115 unsigned char *bc;
3abe9331 1116 int length; // total length, in bytes
1117 int val_bits = 0, len_bits = 0; // only for IntX
970ed795
EL
1118 int value = val.native;
1119 boolean neg_sgbit = (value < 0) && (p_td.raw->comp == SG_SG_BIT);
1120 if (!is_bound()) {
1121 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND,
1122 "Encoding an unbound value.");
1123 value = 0;
1124 neg_sgbit = FALSE;
1125 }
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);
1130 }
970ed795
EL
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);
1134 value = -value;
1135 }
1136 if (neg_sgbit) value = -value;
1137 //myleaf.ext_bit=EXT_BIT_NO;
1138 if (myleaf.must_free) Free(myleaf.body.leaf.data_ptr);
3abe9331 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
1141 int v2 = value;
1142 if (v2 < 0 && p_td.raw->comp == SG_2COMPL) {
1143 v2 = ~v2;
1144 }
1145 do {
1146 v2 >>= 1;
1147 ++val_bits;
1148 }
1149 while (v2 != 0);
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
1154 ++len_bits;
1155 }
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
1165 ++len_bits;
1166 ++length;
1167 }
1168 }
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
1175 }
1176 }
970ed795
EL
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;
1181 }
1182 else bc = myleaf.body.leaf.data_array;
3abe9331 1183 if (p_td.raw->fieldlength == RAW_INTX) {
1184 int i = 0;
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
1189 do {
1190 bc[i] = value & INTX_MASKS[val_bits > 8 ? 8 : val_bits];
1191 ++i;
1192 value >>= 8;
1193 val_bits -= 8;
1194 }
1195 while (val_bits > 0);
1196 if (neg_sgbit) {
1197 // the sign bit is the first bit after the length
1198 unsigned char mask = 0x80 >> len_bits % 8;
1199 bc[i - 1] |= mask;
1200 }
1201 // second, encode the length (ignore the last zero)
1202 --len_bits;
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
1206 --i;
1207 }
1208 else {
1209 // the remainder of the length is in a separate octet
1210 bc[i] = 0;
1211 }
1212 // insert the length's partial octet
1213 unsigned char mask = 0x80;
1214 for (int j = 0; j < len_bits % 8; ++j) {
1215 bc[i] |= mask;
1216 mask >>= 1;
1217 }
1218 if (len_bits % 8 > 0 || val_bits != 0) {
1219 // there was a partial octet => step onto the first full octet
1220 ++i;
1221 }
1222 // insert the length's full octets
1223 while (len_bits >= 8) {
1224 // octets containing only ones in the length
1225 bc[i] = 0xFF;
1226 ++i;
1227 len_bits -= 8;
1228 }
1229 myleaf.length = length * 8;
970ed795 1230 }
3abe9331 1231 else {
1232 for (int a = 0; a < length; a++) {
1233 bc[a] = value & 0xFF;
1234 value >>= 8;
1235 }
1236 if (neg_sgbit) {
1237 unsigned char mask = 0x01 << (p_td.raw->fieldlength - 1) % 8;
1238 bc[length - 1] |= mask;
1239 }
1240 myleaf.length = p_td.raw->fieldlength;
970ed795 1241 }
3abe9331 1242 return myleaf.length;
970ed795
EL
1243}
1244
1245int INTEGER::RAW_encode_openssl(const TTCN_Typedescriptor_t& p_td,
1246 RAW_enc_tree& myleaf) const
1247{
1248 unsigned char *bc = NULL;
3abe9331 1249 int length; // total length, in bytes
1250 int val_bits = 0, len_bits = 0; // only for IntX
970ed795
EL
1251 BIGNUM *D = BN_new();
1252 BN_copy(D, val.openssl);
1253 boolean neg_sgbit = (D->neg) && (p_td.raw->comp == SG_SG_BIT);
1254 if (!is_bound()) {
1255 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND,
1256 "Encoding an unbound value.");
1257 BN_clear(D);
1258 neg_sgbit = FALSE;
1259 }
970ed795
EL
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);
1264 neg_sgbit = FALSE;
1265 }
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);
3abe9331 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
1276 ++len_bits;
1277 }
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
1287 ++len_bits;
1288 ++length;
1289 }
1290 }
1291 else {
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.
1298 BN_clear(D);
1299 neg_sgbit = FALSE;
1300 }
1301 }
970ed795
EL
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;
1307 } else {
1308 bc = myleaf.body.leaf.data_array;
1309 }
1310 boolean twos_compl = (D->neg) && !neg_sgbit;
1311 // Conversion to 2's complement.
1312 if (twos_compl) {
1313 BN_set_negative(D, 0);
1314 for (int a = 0; a < D->dmax; a++) D->d[a] = ~D->d[a];
1315 BN_add_word(D, 1);
1316 }
3abe9331 1317 if (p_td.raw->fieldlength == RAW_INTX) {
1318 int i = 0;
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
1323 do {
1324 bc[i] = (D->top ? D->d[0] : (twos_compl ? 0xFF : 0)) & INTX_MASKS[val_bits > 8 ? 8 : val_bits];
1325 ++i;
1326 BN_rshift(D, D, 8);
1327 val_bits -= 8;
1328 }
1329 while (val_bits > 0);
1330 if (neg_sgbit) {
1331 // the sign bit is the first bit after the length
1332 unsigned char mask = 0x80 >> len_bits % 8;
1333 bc[i - 1] |= mask;
1334 }
1335 // second, encode the length (ignore the last zero)
1336 --len_bits;
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
1340 --i;
1341 }
1342 else {
1343 // the remainder of the length is in a separate octet
1344 bc[i] = 0;
1345 }
1346 // insert the length's partial octet
1347 unsigned char mask = 0x80;
1348 for (int j = 0; j < len_bits % 8; ++j) {
1349 bc[i] |= mask;
1350 mask >>= 1;
1351 }
1352 if (len_bits % 8 > 0 || val_bits != 0) {
1353 // there was a partial octet => step onto the first full octet
1354 ++i;
1355 }
1356 // insert the length's full octets
1357 while (len_bits >= 8) {
1358 // octets containing only ones in the length
1359 bc[i] = 0xFF;
1360 ++i;
1361 len_bits -= 8;
1362 }
1363 myleaf.length = length * 8;
970ed795 1364 }
3abe9331 1365 else {
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;
1370 BN_rshift(D, D, 8);
1371 }
1372 if (neg_sgbit) {
1373 unsigned char mask = 0x01 << (p_td.raw->fieldlength - 1) % 8;
1374 bc[length - 1] |= mask;
1375 }
1376 BN_free(D);
1377 myleaf.length = p_td.raw->fieldlength;
970ed795 1378 }
3abe9331 1379 return myleaf.length;
970ed795
EL
1380}
1381
1382int 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*/)
1385{
1386 bound_flag = FALSE;
1387 int prepaddlength = buff.increase_pos_padd(p_td.raw->prepadding);
1388 limit -= prepaddlength;
3abe9331 1389 RAW_coding_par cp;
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;
1394 orders = FALSE;
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
1406 do {
1407 // check if at least 8 bits are available in the buffer
1408 if (8 > limit) {
1409 if (!no_err) {
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,
1413 len_bits + limit);
1414 }
1415 return -TTCN_EncDec::ET_LEN_ERR;
1416 }
1417 else {
1418 limit -= 8;
1419 }
1420 int nof_unread_bits = buff.unread_len_bit();
1421 if (nof_unread_bits < 8) {
1422 if (!no_err) {
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);
1427 }
1428 return -TTCN_EncDec::ET_INCOMPL_MSG;
1429 }
1430
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;
1434 do {
1435 ++len_bits;
1436 if (len_data & mask) {
1437 mask >>= 1;
1438 }
1439 else {
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;
1443
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);
1447 break;
1448 }
1449 }
1450 while (len_bits % 8 != 0);
1451 }
1452 while (decode_length == 0 && partial_octet_bits == 0);
1453 }
1454 else {
1455 // not IntX, use the static field length
1456 decode_length = p_td.raw->fieldlength;
1457 }
970ed795 1458 if (decode_length > limit) {
3abe9331 1459 if (!no_err) {
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);
1464 }
1465 if (no_err || p_td.raw->fieldlength == RAW_INTX) {
1466 return -TTCN_EncDec::ET_LEN_ERR;
1467 }
970ed795
EL
1468 decode_length = limit;
1469 }
1470 int nof_unread_bits = buff.unread_len_bit();
1471 if (decode_length > nof_unread_bits) {
3abe9331 1472 if (!no_err) {
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);
1477 }
1478 if (no_err || p_td.raw->fieldlength == RAW_INTX) {
1479 return -TTCN_EncDec::ET_INCOMPL_MSG;
1480 }
970ed795
EL
1481 decode_length = nof_unread_bits;
1482 }
1483 clean_up();
1484 if (decode_length < 0) return -1;
3abe9331 1485 else if (decode_length == 0 && partial_octet_bits == 0) {
970ed795
EL
1486 native_flag = TRUE;
1487 val.native = 0;
1488 }
1489 else {
1490 int tmp = 0;
1491 int twos_compl = 0;
3abe9331 1492 unsigned char *data = (unsigned char *) Malloc(
1493 (decode_length + partial_octet_bits + 7) / 8);
970ed795 1494 buff.get_b((size_t) decode_length, data, cp, top_bit_ord);
3abe9331 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;
1500 }
970ed795
EL
1501 int end_pos = decode_length;
1502 int idx = (end_pos - 1) / 8;
1503 boolean negativ_num = FALSE;
1504 switch (p_td.raw->comp) {
1505 case SG_2COMPL:
1506 if (data[idx] >> ((end_pos - 1) % 8) & 0x01) {
1507 tmp = -1;
1508 twos_compl = 1;
1509 }
1510 break;
1511 case SG_NO:
1512 break;
1513 case SG_SG_BIT:
1514 negativ_num = (data[idx] >> ((end_pos - 1) % 8)) & 0x01;
1515 end_pos--;
1516 break;
1517 default:
1518 break;
1519 }
1520 if (end_pos < 9) {
1521 tmp <<= end_pos;
1522 tmp |= data[0] & BitMaskTable[end_pos];
1523 }
1524 else {
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);
1535 pad = 0;
1536 continue;
1537 }
1538 if (pad) continue;
1539 BN_lshift(D, D, 8);
1540 BN_add_word(D, data[idx] & 0xff);
1541 }
1542 if (twos_compl) {
1543 BIGNUM *D_tmp = BN_new();
1544 BN_set_bit(D_tmp, BN_num_bits(D));
1545 BN_sub(D, D, D_tmp);
1546 BN_free(D_tmp);
1547 }
1548 else if (negativ_num) {
1549 BN_set_negative(D, 1);
1550 }
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
1553 // condition.
1554 if (BN_num_bits(D) > (RInt) sizeof(RInt) * 8 - 1) {
1555 native_flag = FALSE;
1556 val.openssl = D;
1557 }
1558 else {
1559 native_flag = TRUE;
1560 val.native = BN_is_negative(D) ? -D->d[0] : D->d[0];
1561 BN_free(D);
1562 }
1563 Free(data);
1564 goto end;
1565 }
1566 else {
1567 for (; idx >= 0; idx--) {
1568 tmp <<= 8;
1569 tmp |= data[idx] & 0xff;
1570 }
1571 }
1572 }
1573 Free(data);
1574 native_flag = TRUE;
1575 val.native = negativ_num ? (RInt) -tmp : (RInt) tmp;
1576 }
1577 end: decode_length += buff.increase_pos_padd(p_td.raw->padding);
1578 bound_flag = TRUE;
3abe9331 1579 return decode_length + prepaddlength + len_bits;
970ed795
EL
1580}
1581
1582int INTEGER::XER_encode(const XERdescriptor_t& p_td, TTCN_Buffer& p_buf,
af710487 1583 unsigned int flavor, int indent, embed_values_enc_struct_t*) const
970ed795
EL
1584{
1585 if (!is_bound()) {
1586 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND,
1587 "Encoding an unbound integer value.");
1588 }
1589 int encoded_length = (int) p_buf.get_len();
1590
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;
1594
1595 char *tmp_str;
1596 if (native_flag)
1597 tmp_str = mprintf("%d", val.native);
1598 else
1599 tmp_str = BN_bn2dec(val.openssl);
1600 CHARSTRING value(tmp_str);
1601 if (native_flag)
1602 Free(tmp_str);
1603 else
1604 OPENSSL_free(tmp_str);
1605 p_buf.put_string(value);
1606
1607 end_xml(p_td, p_buf, flavor, indent, false);
1608
1609 return (int) p_buf.get_len() - encoded_length;
1610}
1611
1612int INTEGER::XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& reader,
feade998 1613 unsigned int flavor, unsigned int /*flavor2*/, embed_values_dec_struct_t*)
970ed795
EL
1614{
1615 const boolean exer = is_exer(flavor);
1616 int depth = -1, success = reader.Ok(), type;
1617 const char * value = 0;
1618
1619 boolean own_tag = !(exer && (p_td.xer_bits & UNTAGGED)) && !is_exerlist(flavor);
1620
1621 if (!own_tag) goto tagless;
1622 if (exer && (p_td.xer_bits & XER_ATTRIBUTE)) {
1623 verify_name(reader, p_td, exer);
1624tagless:
1625 value = (const char *)reader.Value();
1626
1627 for (; *value && isspace(*value); ++value) {}
1628 from_string(value);
1629 if (get_nof_digits() != (int)strlen(value) - (value[0] == '-') ? 1 : 0) {
1630 clean_up();
1631 }
1632 // Let the caller do reader.AdvanceAttribute();
1633 }
1634 else {
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);
1642 }
1643 reader.Read();
1644 break;
1645 }
1646 depth = reader.Depth();
1647 }
1648 else if (XML_READER_TYPE_TEXT == type && depth != -1) {
1649 value = (const char*) reader.Value();
1650 for (; *value && isspace(*value); ++value) {}
1651 from_string(value);
1652 if (get_nof_digits() != (int)strlen(value) - (value[0] == '-') ? 1 : 0) {
1653 clean_up();
1654 }
1655 }
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);
1660 }
1661 reader.Read();
1662 break;
1663 }
1664 } // next read
1665 } // if not attribute
1666
1667 return 1;
1668}
1669
1670int INTEGER::get_nof_digits()
1671{
1672 int digits = 0;
1673 if (native_flag) {
1674 RInt x = val.native;
1675 if (x == 0) return 1;
1676 if (x < 0) x = -x;
1677 while (x > 0) {
1678 ++digits;
1679 x /= 10;
1680 }
1681 } else {
1682 BIGNUM *x = BN_new();
1683 BN_copy(x, val.openssl);
1684 if (BN_is_zero(x)) return 1;
1685 x->neg = 0;
1686 while (!BN_is_zero(x)) {
1687 ++digits;
1688 BN_div_word(x, 10);
1689 }
1690 }
1691 return digits;
1692}
1693
1694int INTEGER::JSON_encode(const TTCN_Typedescriptor_t&, JSON_Tokenizer& p_tok) const
1695{
1696 if (!is_bound()) {
1697 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND,
1698 "Encoding an unbound integer value.");
1699 return -1;
1700 }
1701 char* tmp_str = 0;
1702 if (native_flag) {
1703 tmp_str = mprintf("%d", val.native);
1704 } else {
1705 tmp_str = BN_bn2dec(val.openssl);
1706 }
1707
1708 int enc_len = p_tok.put_next_token(JSON_TOKEN_NUMBER, tmp_str);
1709
1710 if (native_flag) {
1711 Free(tmp_str);
1712 } else {
1713 OPENSSL_free(tmp_str);
1714 }
1715
1716 return enc_len;
1717}
1718
1719int INTEGER::JSON_decode(const TTCN_Typedescriptor_t& p_td, JSON_Tokenizer& p_tok, boolean p_silent)
1720{
1721 json_token_t token = JSON_TOKEN_NONE;
1722 char* value = 0;
1723 size_t value_len = 0;
1724 int dec_len = 0;
1725 boolean use_default = p_td.json->default_value && 0 == p_tok.get_buffer_length();
1726 if (use_default) {
1727 // No JSON data in the buffer -> use default value
1728 value = (char*)p_td.json->default_value;
1729 value_len = strlen(value);
1730 } else {
1731 dec_len = p_tok.get_next_token(&token, &value, &value_len);
1732 }
1733 if (JSON_TOKEN_ERROR == token) {
1734 JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_BAD_TOKEN_ERROR, "");
1735 return JSON_ERROR_FATAL;
1736 }
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)) {
1740 bound_flag = true;
1741 } else {
1742 JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_FORMAT_ERROR, "number", "integer");
1743 bound_flag = false;
1744 dec_len = JSON_ERROR_FATAL;
1745 }
1746 Free(number);
1747 } else {
1748 bound_flag = false;
1749 return JSON_ERROR_INVALID_TOKEN;
1750 }
1751 return dec_len;
1752}
1753
1754
1755// Global functions.
1756
1757INTEGER operator+(int int_value, const INTEGER& other_value)
1758{
1759 other_value.must_bound("Unbound right operand of integer addition.");
1760 return INTEGER(int_value) + other_value;
1761}
1762
1763INTEGER operator-(int int_value, const INTEGER& other_value)
1764{
1765 other_value.must_bound("Unbound right operand of integer subtraction.");
1766 return INTEGER(int_value) - other_value;
1767}
1768
1769INTEGER operator*(int int_value, const INTEGER& other_value)
1770{
1771 other_value.must_bound("Unbound right operand of integer multiplication.");
1772 return INTEGER(int_value) * other_value;
1773}
1774
1775INTEGER operator/(int int_value, const INTEGER& other_value)
1776{
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;
1781}
1782
1783INTEGER rem(int left_value, int right_value)
1784{
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));
1788}
1789
1790INTEGER rem(const INTEGER& left_value, const INTEGER& right_value)
1791{
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);
1795}
1796
1797INTEGER rem(const INTEGER& left_value, int right_value)
1798{
1799 left_value.must_bound("Unbound left operand of rem operator.");
1800 return rem(left_value, INTEGER(right_value));
1801}
1802
1803INTEGER rem(int left_value, const INTEGER& right_value)
1804{
1805 right_value.must_bound("Unbound right operand of rem operator.");
1806 return rem(INTEGER(left_value), right_value);
1807}
1808
1809INTEGER mod(int left_value, int right_value)
1810{
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);
1815 else {
1816 int result = rem(left_value, right_value);
1817 if (result == 0) return 0;
1818 else return INTEGER(right_value + result);
1819 }
1820}
1821
1822INTEGER mod(const INTEGER& left_value, const INTEGER& right_value)
1823{
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);
1832 } else {
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);
1836 }
1837}
1838
1839INTEGER mod(const INTEGER& left_value, int right_value)
1840{
1841 left_value.must_bound("Unbound left operand of mod operator.");
1842 return mod(left_value, INTEGER(right_value));
1843}
1844
1845INTEGER mod(int left_value, const INTEGER& right_value)
1846{
1847 right_value.must_bound("Unbound right operand of mod operator.");
1848 return mod(INTEGER(left_value), right_value);
1849}
1850
1851boolean operator==(int int_value, const INTEGER& other_value)
1852{
1853 other_value.must_bound("Unbound right operand of integer comparison.");
1854 return INTEGER(int_value) == other_value;
1855}
1856
1857boolean operator<(int int_value, const INTEGER& other_value)
1858{
1859 other_value.must_bound("Unbound right operand of integer comparison.");
1860 return INTEGER(int_value) < other_value;
1861}
1862
1863boolean operator>(int int_value, const INTEGER& other_value)
1864{
1865 other_value.must_bound("Unbound right operand of integer comparison.");
1866 return INTEGER(int_value) > other_value;
1867}
1868
1869// Integer template class.
1870
1871void INTEGER_template::clean_up()
1872{
1873 switch (template_selection) {
1874 case SPECIFIC_VALUE:
1875 if (unlikely(!int_val.native_flag)) BN_free(int_val.val.openssl);
1876 break;
1877 case VALUE_LIST:
1878 case COMPLEMENTED_LIST:
1879 delete [] value_list.list_value;
1880 break;
1881 case VALUE_RANGE:
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);
1886 break;
1887 default:
1888 break;
1889 }
1890 template_selection = UNINITIALIZED_TEMPLATE;
1891}
1892
1893void INTEGER_template::copy_template(const INTEGER_template& other_value)
1894{
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);
1901 break;
1902 case OMIT_VALUE:
1903 case ANY_VALUE:
1904 case ANY_OR_OMIT:
1905 break;
1906 case VALUE_LIST:
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]);
1913 break;
1914 case VALUE_RANGE:
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;
1921 else
1922 value_range.min_value.val.openssl =
1923 BN_dup(other_value.value_range.min_value.val.openssl);
1924 }
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;
1931 else
1932 value_range.max_value.val.openssl =
1933 BN_dup(other_value.value_range.max_value.val.openssl);
1934 }
1935 break;
1936 default:
1937 TTCN_error("Copying an uninitialized/unsupported integer template.");
1938 }
1939 set_selection(other_value);
1940}
1941
1942INTEGER_template::INTEGER_template()
1943{
1944}
1945
1946INTEGER_template::INTEGER_template(template_sel other_value)
1947 : Base_Template(other_value)
1948{
1949 check_single_selection(other_value);
1950}
1951
1952INTEGER_template::INTEGER_template(int other_value)
1953 : Base_Template(SPECIFIC_VALUE)
1954{
1955 int_val.native_flag = TRUE;
1956 int_val.val.native = other_value;
1957}
1958
1959INTEGER_template::INTEGER_template(const INTEGER& other_value)
1960 : Base_Template(SPECIFIC_VALUE)
1961{
1962 other_value.must_bound("Creating a template from an unbound integer "
1963 "value.");
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);
1969}
1970
1971INTEGER_template::INTEGER_template(const OPTIONAL<INTEGER>& other_value)
1972{
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);
1981 break; }
1982 case OPTIONAL_OMIT:
1983 set_selection(OMIT_VALUE);
1984 break;
1985 default:
1986 TTCN_error("Creating an integer template from an unbound optional field.");
1987 }
1988}
1989
1990INTEGER_template::INTEGER_template(const INTEGER_template& other_value)
1991: Base_Template()
1992{
1993 copy_template(other_value);
1994}
1995
1996INTEGER_template::~INTEGER_template()
1997{
1998 clean_up();
1999}
2000
2001INTEGER_template& INTEGER_template::operator=(template_sel other_value)
2002{
2003 check_single_selection(other_value);
2004 clean_up();
2005 set_selection(other_value);
2006 return *this;
2007}
2008
2009INTEGER_template& INTEGER_template::operator=(int other_value)
2010{
2011 clean_up();
2012 set_selection(SPECIFIC_VALUE);
2013 int_val.native_flag = TRUE;
2014 int_val.val.native = other_value;
2015 return *this;
2016}
2017
2018INTEGER_template& INTEGER_template::operator=(const INTEGER& other_value)
2019{
2020 other_value.must_bound("Assignment of an unbound integer value to a "
2021 "template.");
2022 clean_up();
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);
2029 return *this;
2030}
2031
2032INTEGER_template& INTEGER_template::operator=
2033 (const OPTIONAL<INTEGER>& other_value)
2034{
2035 clean_up();
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);
2044 break; }
2045 case OPTIONAL_OMIT:
2046 set_selection(OMIT_VALUE);
2047 break;
2048 default:
2049 TTCN_error("Assignment of an unbound optional field to an integer "
2050 "template.");
2051 }
2052 return *this;
2053}
2054
2055INTEGER_template& INTEGER_template::operator=
2056 (const INTEGER_template& other_value)
2057{
2058 if (&other_value != this) {
2059 clean_up();
2060 copy_template(other_value);
2061 }
2062 return *this;
2063}
2064
3abe9331 2065boolean INTEGER_template::match(int other_value, boolean /* legacy */) const
970ed795
EL
2066{
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;
2071 case OMIT_VALUE:
2072 return FALSE;
2073 case ANY_VALUE:
2074 case ANY_OR_OMIT:
2075 return TRUE;
2076 case VALUE_LIST:
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;
2082 case VALUE_RANGE: {
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;
2090 }
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;
2096 }
2097 return lower_boundary && upper_boundary; }
2098 default:
2099 TTCN_error("Matching with an uninitialized/unsupported integer "
2100 "template.");
2101 }
2102 return FALSE;
2103}
2104
3abe9331 2105boolean INTEGER_template::match(const INTEGER& other_value,
2106 boolean /* legacy */) const
970ed795
EL
2107{
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(); }
2114 case OMIT_VALUE:
2115 return FALSE;
2116 case ANY_VALUE:
2117 case ANY_OR_OMIT:
2118 return TRUE;
2119 case VALUE_LIST:
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;
2125 case VALUE_RANGE: {
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();
2133 }
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();
2139 }
2140 return lower_boundary && upper_boundary; }
2141 default:
2142 TTCN_error("Matching with an uninitialized/unsupported integer "
2143 "template.");
2144 }
2145 return FALSE;
2146}
2147
2148INTEGER INTEGER_template::valueof() const
2149{
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));
2155}
2156
2157void INTEGER_template::set_type(template_sel template_type,
2158 unsigned int list_length)
2159{
2160 clean_up();
2161 switch (template_type) {
2162 case VALUE_LIST:
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];
2167 break;
2168 case VALUE_RANGE:
2169 set_selection(VALUE_RANGE);
2170 value_range.min_is_present = FALSE;
2171 value_range.max_is_present = FALSE;
2172 break;
2173 default:
2174 TTCN_error("Setting an invalid type for an integer template.");
2175 }
2176}
2177
2178INTEGER_template& INTEGER_template::list_item(unsigned int list_index)
2179{
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];
2186}
2187
2188void INTEGER_template::set_min(int min_value)
2189{
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.");
2199 }
2200 value_range.min_is_present = TRUE;
2201 value_range.min_value.native_flag = TRUE;
2202 value_range.min_value.val.native = min_value;
2203}
2204
2205void INTEGER_template::set_min(const INTEGER& min_value)
2206{
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.");
2220 }
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);
2226}
2227
2228void INTEGER_template::set_max(int max_value)
2229{
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.");
2239 }
2240 value_range.max_is_present = TRUE;
2241 value_range.max_value.native_flag = TRUE;
2242 value_range.max_value.val.native = max_value;
2243}
2244
2245void INTEGER_template::set_max(const INTEGER& max_value)
2246{
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.");
2259 }
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);
2265}
2266
2267void INTEGER_template::log() const
2268{
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);
2275 Free(tmp_str);
2276 break; }
2277 case COMPLEMENTED_LIST:
2278 TTCN_Logger::log_event_str("complement ");
2279 // no break
2280 case VALUE_LIST:
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();
2285 }
2286 TTCN_Logger::log_char(')');
2287 break;
2288 case VALUE_RANGE:
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);
2296 Free(min_str);
2297 } else {
2298 TTCN_Logger::log_event_str("-infinity");
2299 }
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);
2307 Free(max_str);
2308 } else {
2309 TTCN_Logger::log_event_str("infinity");
2310 }
2311 TTCN_Logger::log_char(')');
2312 break;
2313 default:
2314 log_generic();
2315 break;
2316 }
2317 log_ifpresent();
2318}
2319
3abe9331 2320void INTEGER_template::log_match(const INTEGER& match_value,
2321 boolean /* legacy */) const
970ed795
EL
2322{
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(" := ");
2327 }
2328 match_value.log();
2329 TTCN_Logger::log_event_str(" with ");
2330 log();
2331 if (match(match_value)) TTCN_Logger::log_event_str(" matched");
2332 else TTCN_Logger::log_event_str(" unmatched");
2333}
2334
2335void INTEGER_template::set_param(Module_Param& param) {
2336 param.basic_check(Module_Param::BC_TEMPLATE, "integer template");
3abe9331 2337 Module_Param_Ptr mp = &param;
2338 if (param.get_type() == Module_Param::MP_Reference) {
2339 mp = param.get_referenced_param();
2340 }
2341 switch (mp->get_type()) {
970ed795
EL
2342 case Module_Param::MP_Omit:
2343 *this = OMIT_VALUE;
2344 break;
2345 case Module_Param::MP_Any:
2346 *this = ANY_VALUE;
2347 break;
2348 case Module_Param::MP_AnyOrNone:
2349 *this = ANY_OR_OMIT;
2350 break;
2351 case Module_Param::MP_List_Template:
3abe9331 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));
970ed795 2358 }
3abe9331 2359 *this = temp;
2360 break; }
970ed795
EL
2361 case Module_Param::MP_Integer: {
2362 INTEGER tmp;
3abe9331 2363 tmp.set_val(*mp->get_integer());
970ed795
EL
2364 *this = tmp;
2365 } break;
2366 case Module_Param::MP_IntRange: {
2367 set_type(VALUE_RANGE);
3abe9331 2368 if (mp->get_lower_int()!=NULL) {
970ed795 2369 INTEGER tmp;
3abe9331 2370 tmp.set_val(*mp->get_lower_int());
970ed795
EL
2371 set_min(tmp);
2372 }
3abe9331 2373 if (mp->get_upper_int()!=NULL) {
970ed795 2374 INTEGER tmp;
3abe9331 2375 tmp.set_val(*mp->get_upper_int());
970ed795
EL
2376 set_max(tmp);
2377 }
2378 } break;
3abe9331 2379 case Module_Param::MP_Expression:
2380 switch (mp->get_expr_type()) {
2381 case Module_Param::EXPR_NEGATE: {
2382 INTEGER operand;
2383 operand.set_param(*mp->get_operand1());
2384 *this = - operand;
2385 break; }
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;
2391 break; }
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;
2397 break; }
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;
2403 break; }
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.");
2410 }
2411 *this = operand1 / operand2;
2412 break; }
2413 default:
2414 param.expr_type_error("an integer");
2415 break;
2416 }
2417 break;
970ed795
EL
2418 default:
2419 param.type_error("integer template");
2420 }
3abe9331 2421 is_ifpresent = param.get_ifpresent() || mp->get_ifpresent();
2422}
2423
2424Module_Param* INTEGER_template::get_param(Module_Param_Name& param_name) const
2425{
2426 Module_Param* mp = NULL;
2427 switch (template_selection) {
2428 case UNINITIALIZED_TEMPLATE:
2429 mp = new Module_Param_Unbound();
2430 break;
2431 case OMIT_VALUE:
2432 mp = new Module_Param_Omit();
2433 break;
2434 case ANY_VALUE:
2435 mp = new Module_Param_Any();
2436 break;
2437 case ANY_OR_OMIT:
2438 mp = new Module_Param_AnyOrNone();
2439 break;
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));
2443 }
2444 else {
2445 mp = new Module_Param_Integer(new int_val_t(BN_dup(int_val.val.openssl)));
2446 }
2447 break;
2448 case VALUE_LIST:
2449 case COMPLEMENTED_LIST: {
2450 if (template_selection == VALUE_LIST) {
2451 mp = new Module_Param_List_Template();
2452 }
2453 else {
2454 mp = new Module_Param_ComplementList_Template();
2455 }
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));
2458 }
2459 break; }
2460 case VALUE_RANGE: {
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);
2466 }
2467 else {
2468 lower_bound = new int_val_t(BN_dup(value_range.min_value.val.openssl));
2469 }
2470 }
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);
2474 }
2475 else {
2476 upper_bound = new int_val_t(BN_dup(value_range.max_value.val.openssl));
2477 }
2478 }
2479 mp = new Module_Param_IntRange(lower_bound, upper_bound);
2480 break; }
2481 default:
2482 break;
2483 }
2484 if (is_ifpresent) {
2485 mp->set_ifpresent();
2486 }
2487 return mp;
970ed795
EL
2488}
2489
2490void INTEGER_template::encode_text(Text_Buf& text_buf) const
2491{
2492 encode_text_base(text_buf);
2493 switch (template_selection) {
2494 case OMIT_VALUE:
2495 case ANY_VALUE:
2496 case ANY_OR_OMIT:
2497 break;
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)));
2501 break;
2502 case VALUE_LIST:
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);
2507 break;
2508 case VALUE_RANGE:
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)));
2519 break;
2520 default:
2521 TTCN_error("Text encoder: Encoding an uninitialized/unsupported integer "
2522 "template.");
2523 }
2524}
2525
2526void INTEGER_template::decode_text(Text_Buf& text_buf)
2527{
2528 clean_up();
2529 decode_text_base(text_buf);
2530 switch (template_selection) {
2531 case OMIT_VALUE:
2532 case ANY_VALUE:
2533 case ANY_OR_OMIT:
2534 break;
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);
2540 break; }
2541 case VALUE_LIST:
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);
2547 break;
2548 case VALUE_RANGE:
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);
2556 }
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);
2564 }
2565 break;
2566 default:
2567 TTCN_error("Text decoder: An unknown/unsupported selection was received "
2568 "for an integer template.");
2569 }
2570}
2571
3abe9331 2572boolean INTEGER_template::is_present(boolean legacy /* = FALSE */) const
970ed795
EL
2573{
2574 if (template_selection==UNINITIALIZED_TEMPLATE) return FALSE;
3abe9331 2575 return !match_omit(legacy);
970ed795
EL
2576}
2577
3abe9331 2578boolean INTEGER_template::match_omit(boolean legacy /* = FALSE */) const
970ed795
EL
2579{
2580 if (is_ifpresent) return TRUE;
2581 switch (template_selection) {
2582 case OMIT_VALUE:
2583 case ANY_OR_OMIT:
2584 return TRUE;
2585 case VALUE_LIST:
2586 case COMPLEMENTED_LIST:
3abe9331 2587 if (legacy) {
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;
2593 }
2594 // else fall through
970ed795
EL
2595 default:
2596 return FALSE;
2597 }
2598 return FALSE;
2599}
2600
2601#ifndef TITAN_RUNTIME_2
3abe9331 2602void INTEGER_template::check_restriction(template_res t_res, const char* t_name,
2603 boolean legacy /* = FALSE */) const
970ed795
EL
2604{
2605 if (template_selection==UNINITIALIZED_TEMPLATE) return;
2606 switch ((t_name&&(t_res==TR_VALUE))?TR_OMIT:t_res) {
2607 case TR_VALUE:
2608 if (!is_ifpresent && template_selection==SPECIFIC_VALUE) return;
2609 break;
2610 case TR_OMIT:
2611 if (!is_ifpresent && (template_selection==OMIT_VALUE ||
2612 template_selection==SPECIFIC_VALUE)) return;
2613 break;
2614 case TR_PRESENT:
3abe9331 2615 if (!match_omit(legacy)) return;
970ed795
EL
2616 break;
2617 default:
2618 return;
2619 }
2620 TTCN_error("Restriction `%s' on template of type %s violated.",
2621 get_res_name(t_res), t_name ? t_name : "integer");
2622}
2623#endif
This page took 0.121051 seconds and 5 git commands to generate.