1 ///////////////////////////////////////////////////////////////////////////////
2 // Copyright (c) 2000-2014 Ericsson Telecom AB
3 // All rights reserved. This program and the accompanying materials
4 // are made available under the terms of the Eclipse Public License v1.0
5 // which accompanies this distribution, and is available at
6 // http://www.eclipse.org/legal/epl-v10.html
7 ///////////////////////////////////////////////////////////////////////////////
12 #include "../common/memory.h"
15 #include "Param_Types.hh"
16 #include "Optional.hh"
22 #include "Charstring.hh"
24 #include "XmlReader.hh"
26 #include "../common/dbgnew.hh"
30 #define INFINITY (DBL_MAX*DBL_MAX)
32 const FLOAT
PLUS_INFINITY(INFINITY
);
33 const FLOAT
MINUS_INFINITY(-INFINITY
);
36 const FLOAT
NOT_A_NUMBER(NAN
);
38 const FLOAT
NOT_A_NUMBER((double)PLUS_INFINITY
+(double)MINUS_INFINITY
);
39 // The casts ensure that FLOAT::operator+ is not called
43 static inline void log_float(double float_val
)
45 if ( (float_val
> -MAX_DECIMAL_FLOAT
&& float_val
<= -MIN_DECIMAL_FLOAT
)
46 || (float_val
>= MIN_DECIMAL_FLOAT
&& float_val
< MAX_DECIMAL_FLOAT
)
47 || (float_val
== 0.0))
48 TTCN_Logger::log_event("%f", float_val
);
49 else if(float_val
==INFINITY
)
50 TTCN_Logger::log_event_str("infinity");
51 else if(float_val
==-INFINITY
)
52 TTCN_Logger::log_event_str("-infinity");
53 else if(float_val
!=float_val
)
54 TTCN_Logger::log_event_str("not_a_number");
55 else TTCN_Logger::log_event("%e", float_val
);
65 FLOAT::FLOAT(double other_value
)
68 float_value
= other_value
;
71 FLOAT::FLOAT(const FLOAT
& other_value
)
72 : Base_Type(other_value
)
74 other_value
.must_bound("Copying an unbound float value.");
76 float_value
= other_value
.float_value
;
79 void FLOAT::clean_up()
84 FLOAT
& FLOAT::operator=(double other_value
)
87 float_value
= other_value
;
91 FLOAT
& FLOAT::operator=(const FLOAT
& other_value
)
93 other_value
.must_bound("Assignment of an unbound float value.");
95 float_value
= other_value
.float_value
;
99 double FLOAT::operator+() const
101 must_bound("Unbound float operand of unary + operator.");
105 double FLOAT::operator-() const
107 must_bound("Unbound float operand of unary - operator (negation).");
111 bool FLOAT::is_special(double flt_val
)
113 return ( (flt_val
!=flt_val
) || (flt_val
==INFINITY
) || (flt_val
==-INFINITY
) );
116 void FLOAT::check_numeric(double flt_val
, const char *err_msg_begin
)
118 if (is_special(flt_val
)) {
119 TTCN_error("%s must be a numeric value instead of %g",
120 err_msg_begin
, flt_val
);
124 double FLOAT::operator+(double other_value
) const
126 must_bound("Unbound left operand of float addition.");
127 check_numeric(float_value
, "Left operand of float addition");
128 check_numeric(other_value
, "Right operand of float addition");
129 return float_value
+ other_value
;
132 double FLOAT::operator+(const FLOAT
& other_value
) const
134 must_bound("Unbound left operand of float addition.");
135 other_value
.must_bound("Unbound right operand of float addition.");
136 check_numeric(float_value
, "Left operand of float addition");
137 check_numeric(other_value
.float_value
, "Right operand of float addition");
138 return float_value
+ other_value
.float_value
;
141 double FLOAT::operator-(double other_value
) const
143 must_bound("Unbound left operand of float subtraction.");
144 check_numeric(float_value
, "Left operand of float subtraction");
145 check_numeric(other_value
, "Right operand of float subtraction");
146 return float_value
- other_value
;
149 double FLOAT::operator-(const FLOAT
& other_value
) const
151 must_bound("Unbound left operand of float subtraction.");
152 other_value
.must_bound("Unbound right operand of float subtraction.");
153 check_numeric(float_value
, "Left operand of float subtraction");
154 check_numeric(other_value
.float_value
, "Right operand of float subtraction");
155 return float_value
- other_value
.float_value
;
158 double FLOAT::operator*(double other_value
) const
160 must_bound("Unbound left operand of float multiplication.");
161 check_numeric(float_value
, "Left operand of float multiplication");
162 check_numeric(other_value
, "Right operand of float multiplication");
163 return float_value
* other_value
;
166 double FLOAT::operator*(const FLOAT
& other_value
) const
168 must_bound("Unbound left operand of float multiplication.");
169 other_value
.must_bound("Unbound right operand of float multiplication.");
170 check_numeric(float_value
, "Left operand of float multiplication");
171 check_numeric(other_value
.float_value
, "Right operand of float multiplication");
172 return float_value
* other_value
.float_value
;
175 double FLOAT::operator/(double other_value
) const
177 must_bound("Unbound left operand of float division.");
178 check_numeric(float_value
, "Left operand of float division");
179 check_numeric(other_value
, "Right operand of float division");
180 if (other_value
== 0.0) TTCN_error("Float division by zero.");
181 return float_value
/ other_value
;
184 double FLOAT::operator/(const FLOAT
& other_value
) const
186 must_bound("Unbound left operand of float division.");
187 other_value
.must_bound("Unbound right operand of float division.");
188 check_numeric(float_value
, "Left operand of float division");
189 check_numeric(other_value
.float_value
, "Right operand of float division");
190 if (other_value
.float_value
== 0.0) TTCN_error("Float division by zero.");
191 return float_value
/ other_value
.float_value
;
194 boolean
FLOAT::operator==(double other_value
) const
196 must_bound("Unbound left operand of float comparison.");
197 return float_value
== other_value
;
200 boolean
FLOAT::operator==(const FLOAT
& other_value
) const
202 must_bound("Unbound left operand of float comparison.");
203 other_value
.must_bound("Unbound right operand of float comparison.");
204 return float_value
== other_value
.float_value
;
207 boolean
FLOAT::operator<(double other_value
) const
209 must_bound("Unbound left operand of float comparison.");
210 return float_value
< other_value
;
213 boolean
FLOAT::operator<(const FLOAT
& other_value
) const
215 must_bound("Unbound left operand of float comparison.");
216 other_value
.must_bound("Unbound right operand of float comparison.");
217 return float_value
< other_value
.float_value
;
220 boolean
FLOAT::operator>(double other_value
) const
222 must_bound("Unbound left operand of float comparison.");
223 return float_value
> other_value
;
226 boolean
FLOAT::operator>(const FLOAT
& other_value
) const
228 must_bound("Unbound left operand of float comparison.");
229 other_value
.must_bound("Unbound right operand of float comparison.");
230 return float_value
> other_value
.float_value
;
233 FLOAT::operator double() const
235 must_bound("Using the value of an unbound float variable.");
239 void FLOAT::log() const
241 if (bound_flag
) log_float(float_value
);
242 else TTCN_Logger::log_event_unbound();
245 void FLOAT::set_param(Module_Param
& param
) {
246 param
.basic_check(Module_Param::BC_VALUE
, "float value");
247 if (param
.get_type()!=Module_Param::MP_Float
) param
.type_error("float value");
249 float_value
= param
.get_float();
252 void FLOAT::encode_text(Text_Buf
& text_buf
) const
254 must_bound("Text encoder: Encoding an unbound float value.");
255 text_buf
.push_double(float_value
);
258 void FLOAT::decode_text(Text_Buf
& text_buf
)
261 float_value
= text_buf
.pull_double();
264 void FLOAT::encode(const TTCN_Typedescriptor_t
& p_td
, TTCN_Buffer
& p_buf
,
265 TTCN_EncDec::coding_t p_coding
, ...) const
268 va_start(pvar
, p_coding
);
270 case TTCN_EncDec::CT_BER
: {
271 TTCN_EncDec_ErrorContext
ec("While BER-encoding type '%s': ", p_td
.name
);
272 unsigned BER_coding
=va_arg(pvar
, unsigned);
273 BER_encode_chk_coding(BER_coding
);
274 ASN_BER_TLV_t
*tlv
=BER_encode_TLV(p_td
, BER_coding
);
275 tlv
->put_in_buffer(p_buf
);
276 ASN_BER_TLV_t::destruct(tlv
);
278 case TTCN_EncDec::CT_RAW
: {
279 TTCN_EncDec_ErrorContext
ec("While RAW-encoding type '%s': ", p_td
.name
);
281 TTCN_EncDec_ErrorContext::error_internal
282 ("No RAW descriptor available for type '%s'.", p_td
.name
);
286 RAW_enc_tree
root(TRUE
,NULL
,&rp
,1,p_td
.raw
);
287 RAW_encode(p_td
, root
);
288 root
.put_to_buf(p_buf
);
290 case TTCN_EncDec::CT_XER
: {
291 TTCN_EncDec_ErrorContext
ec("While XER-encoding type '%s': ", p_td
.name
);
292 unsigned XER_coding
=va_arg(pvar
, unsigned);
293 XER_encode(*p_td
.xer
, p_buf
, XER_coding
, 0, 0);
295 case TTCN_EncDec::CT_JSON
: {
296 TTCN_EncDec_ErrorContext
ec("While JSON-encoding type '%s': ", p_td
.name
);
298 TTCN_EncDec_ErrorContext::error_internal
299 ("No JSON descriptor available for type '%s'.", p_td
.name
);
300 JSON_Tokenizer
tok(va_arg(pvar
, int) != 0);
301 JSON_encode(p_td
, tok
);
302 p_buf
.put_s(tok
.get_buffer_length(), (const unsigned char*)tok
.get_buffer());
305 TTCN_error("Unknown coding method requested to encode type '%s'",
311 void FLOAT::decode(const TTCN_Typedescriptor_t
& p_td
, TTCN_Buffer
& p_buf
,
312 TTCN_EncDec::coding_t p_coding
, ...)
315 va_start(pvar
, p_coding
);
317 case TTCN_EncDec::CT_BER
: {
318 TTCN_EncDec_ErrorContext
ec("While BER-decoding type '%s': ", p_td
.name
);
319 unsigned L_form
=va_arg(pvar
, unsigned);
321 BER_decode_str2TLV(p_buf
, tlv
, L_form
);
322 BER_decode_TLV(p_td
, tlv
, L_form
);
323 if(tlv
.isComplete
) p_buf
.increase_pos(tlv
.get_len());
325 case TTCN_EncDec::CT_RAW
: {
326 TTCN_EncDec_ErrorContext
ec("While RAW-decoding type '%s': ", p_td
.name
);
328 TTCN_EncDec_ErrorContext::error_internal
329 ("No RAW descriptor available for type '%s'.", p_td
.name
);
331 switch(p_td
.raw
->top_bit_order
){
339 if(RAW_decode(p_td
, p_buf
, p_buf
.get_len()*8, order
)<0)
340 ec
.error(TTCN_EncDec::ET_INCOMPL_MSG
,
341 "Can not decode type '%s', because invalid or incomplete"
342 " message was received"
345 case TTCN_EncDec::CT_XER
: {
346 TTCN_EncDec_ErrorContext
ec("While XER-decoding type '%s': ", p_td
.name
);
347 unsigned XER_coding
=va_arg(pvar
, unsigned);
348 XmlReaderWrap
reader(p_buf
);
349 for (int success
= reader
.Read(); success
==1; success
=reader
.Read()) {
350 int type
= reader
.NodeType();
351 if (type
==XML_READER_TYPE_ELEMENT
)
354 XER_decode(*p_td
.xer
, reader
, XER_coding
, 0);
355 size_t bytes
= reader
.ByteConsumed();
356 p_buf
.set_pos(bytes
);
358 case TTCN_EncDec::CT_JSON
: {
359 TTCN_EncDec_ErrorContext
ec("While JSON-decoding type '%s': ", p_td
.name
);
361 TTCN_EncDec_ErrorContext::error_internal
362 ("No JSON descriptor available for type '%s'.", p_td
.name
);
363 JSON_Tokenizer
tok((const char*)p_buf
.get_data(), p_buf
.get_len());
364 if(JSON_decode(p_td
, tok
, false)<0)
365 ec
.error(TTCN_EncDec::ET_INCOMPL_MSG
,
366 "Can not decode type '%s', because invalid or incomplete"
367 " message was received"
369 p_buf
.set_pos(tok
.get_buf_pos());
372 TTCN_error("Unknown coding method requested to decode type '%s'",
379 FLOAT::BER_encode_TLV(const TTCN_Typedescriptor_t
& p_td
,
380 unsigned p_coding
) const
383 ASN_BER_TLV_t
*new_tlv
=BER_encode_chk_bound(is_bound());
385 if(float_value
==0.0) {
386 new_tlv
=ASN_BER_TLV_t::construct();
387 // nothing to do, Vlen is 0
390 else if(float_value
==(double)INFINITY
) { // INFINITY may be float => cast
391 new_tlv
=ASN_BER_TLV_t::construct(1, NULL
);
392 new_tlv
->V
.str
.Vstr
[0]=0x40;
395 else if(float_value
==-(double)INFINITY
) {
396 new_tlv
=ASN_BER_TLV_t::construct(1, NULL
);
397 new_tlv
->V
.str
.Vstr
[0]=0x41;
399 else if(isnan((double)float_value
)) {
400 TTCN_EncDec_ErrorContext::error_internal("Value is NaN.");
403 new_tlv
=ASN_BER_TLV_t::construct();
404 double mantissa
, exponent
;
405 exponent
=floor(log10(fabs(float_value
)))+1.0-DBL_DIG
;
406 mantissa
=floor(float_value
*pow(10.0,-exponent
)+0.5);
407 if(mantissa
)while(!fmod(mantissa
,10.0))mantissa
/=10.0,exponent
+=1.0;
411 warning: `.' not followed by `*' or digit in format
413 new_tlv
->V
.str
.Vstr
=(unsigned char*)
414 mprintf("\x03%.f.E%s%.0f", mantissa
, exponent
==0.0?"+":"", exponent
);
415 new_tlv
->V
.str
.Vlen
=1+strlen((const char*)&new_tlv
->V
.str
.Vstr
[1]);
418 new_tlv
=ASN_BER_V2TLV(new_tlv
, p_td
, p_coding
);
422 boolean
FLOAT::BER_decode_TLV(const TTCN_Typedescriptor_t
& p_td
,
423 const ASN_BER_TLV_t
& p_tlv
,
428 ASN_BER_TLV_t stripped_tlv
;
429 BER_decode_strip_tags(*p_td
.ber
, p_tlv
, L_form
, stripped_tlv
);
430 TTCN_EncDec_ErrorContext
ec("While decoding REAL type: ");
431 stripped_tlv
.chk_constructed_flag(FALSE
);
432 if (!stripped_tlv
.isComplete
) return FALSE
;
433 size_t Vlen
=stripped_tlv
.V
.str
.Vlen
;
434 unsigned char *Vstr
=stripped_tlv
.V
.str
.Vstr
;
438 else if(Vstr
[0] & 0x80) {
439 /* binary encoding */
440 /** \todo Perhaps it were good to implement this. Perhaps not. :) */
441 ec
.warning("Sorry, decoding of binary encoded REAL values not"
445 else if(Vstr
[0] & 0x40) {
446 /* SpecialRealValue */
448 ec
.error(TTCN_EncDec::ET_INVAL_MSG
,
449 "In case of SpecialRealValue, the length of V-part must be 1"
450 " (See X.690 8.5.8).");
452 ec
.error(TTCN_EncDec::ET_INVAL_MSG
,
453 "This is a reserved value: 0x%x (See X.690 8.5.8).",
457 float_value
=-INFINITY
;
460 float_value
=INFINITY
;
463 /* decimal encoding */
464 if((Vstr
[0] & 0x3C) || (Vstr
[0] & 0x3F) == 0x00 )
465 ec
.error(TTCN_EncDec::ET_INVAL_MSG
,
466 "This is a reserved value: 0x%x (See X.690 8.5.7).",
468 int NR
=Vstr
[0] & 0x03; // which NumericalRepresentation
473 *Vstr_last
=Vstr
+Vlen
-1,
487 if(Vlen
==1) goto dec_error
;
489 if(ptr
==Vstr_last
) goto dec_error
;
492 if(*ptr
=='+' || *ptr
=='-') {
494 if(ptr
==Vstr_last
) goto dec_error
;
499 if(ptr
==Vstr_last
) goto str_end
;
502 while(*ptr
>='0' && *ptr
<='9') {
503 if(mant1_len
==0) mant1
=ptr
;
505 if(ptr
==Vstr_last
) goto str_end
;
508 if(*ptr
=='.' || *ptr
==',') {
510 if(ptr
==Vstr_last
) goto str_end
;
513 while(*ptr
>='0' && *ptr
<='9') {
514 if(mant2_len
==0) mant2
=ptr
;
516 if(ptr
==Vstr_last
) goto str_end
;
519 if(!leadingzero
&& !mant1
&& !mant2
) goto dec_error
;
520 if(*ptr
=='e' || *ptr
=='E') {
522 if(ptr
==Vstr_last
) goto dec_error
;
525 if(*ptr
=='+' || *ptr
=='-') {
527 if(ptr
==Vstr_last
) goto dec_error
;
532 if(ptr
==Vstr_last
) goto str_end
;
535 while(*ptr
>='0' && *ptr
<='9') {
536 if(expo_len
==0) expo
=ptr
;
538 if(ptr
==Vstr_last
) goto str_end
;
541 if(expo_len
==0 && expo
!=NULL
) expo_len
=1; /* only leading zero */
542 if(expsign
&& !expo
) goto dec_error
;
543 ec
.error(TTCN_EncDec::ET_INVAL_MSG
,
544 "Superfluous part at the end of decimal encoding.");
548 if(decmark
|| expmark
) NR_error
=TRUE
;
551 if(expmark
) NR_error
=TRUE
;
554 ec
.error(TTCN_EncDec::ET_INVAL_MSG
,
555 "This decimal encoding does not conform to NR%d form.", NR
);
556 while(mant2_len
>1 && mant2
[mant2_len
-1]=='0') mant2_len
--;
557 if(mant2_len
==1 && *mant2
=='0') mant2_len
=0, mant2
=NULL
;
559 if(mant1
) for(size_t i
=0; i
<mant1_len
; i
++) {
561 float_value
+=static_cast<double>(mant1
[i
]-'0');
563 if(mant2
) for(size_t i
=0; i
<mant2_len
; i
++) {
565 float_value
+=static_cast<double>(mant2
[i
]-'0');
569 if(ceil(log10(log10(DBL_MAX
)))<expo_len
) {
571 if(expsign
&& *expsign
=='-') {
575 if(sign
&& *sign
=='-') float_value
=-INFINITY
;
576 else float_value
=INFINITY
;
582 for(size_t i
=0; i
<expo_len
; i
++) {
584 exponum
+=static_cast<int>(expo
[i
]-'0');
586 if(expsign
&& *expsign
=='-')
590 if(mant2
) exponum
-=mant2_len
;
591 float_value
*=pow(10.0, static_cast<double>(exponum
));
594 ec
.error(TTCN_EncDec::ET_INVAL_MSG
, "Erroneous decimal encoding.");
602 int FLOAT::RAW_encode(const TTCN_Typedescriptor_t
& p_td
, RAW_enc_tree
& myleaf
) const
606 int length
= p_td
.raw
->fieldlength
/ 8;
607 double tmp
= float_value
;
609 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND
,
610 "Encoding an unbound value.");
614 TTCN_EncDec_ErrorContext::error_internal("Value is NaN.");
616 if (myleaf
.must_free
) Free(myleaf
.body
.leaf
.data_ptr
);
617 if (length
> RAW_INT_ENC_LENGTH
) {
618 myleaf
.body
.leaf
.data_ptr
= bc
= (unsigned char*)Malloc(length
*sizeof(*bc
));
619 myleaf
.must_free
= TRUE
;
620 myleaf
.data_ptr_used
= TRUE
;
623 bc
= myleaf
.body
.leaf
.data_array
;
626 dv
= (unsigned char *) &tmp
;
627 #if defined __sparc__ || defined __sparc
630 for (int i
= 0, k
= 7; i
< 8; i
++, k
--) bc
[i
] = dv
[k
];
633 else if (length
== 4) {
634 if (tmp
== 0.0) memset(bc
, 0, 4);
635 else if (tmp
== -0.0) {
640 #if defined __sparc__ || defined __sparc
647 dv
= (unsigned char *) &tmp
;
648 bc
[0] = dv
[index
] & 0x80;
649 int exponent
= dv
[index
] & 0x7F;
652 exponent
+= (dv
[index
] & 0xF0) >> 4;
655 if (exponent
> 127) {
656 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_LEN_ERR
,
657 "The float value '%f' is out of the range of "
658 "the single precision: %s", (double)float_value
, p_td
.name
);
662 else if (exponent
< -127) {
663 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_FLOAT_TR
,
664 "The float value '%f' is too small to represent it "
665 "in single precision: %s", (double)float_value
, p_td
.name
);
669 else exponent
+= 127;
670 bc
[0] |= (exponent
>> 1) & 0x7F;
671 bc
[1] = ((exponent
<< 7) & 0x80) | ((dv
[index
] & 0x0F) << 3)
672 | ((dv
[index
+ adj
] & 0xE0) >> 5);
674 bc
[2] = ((dv
[index
] & 0x1F) << 3) | ((dv
[index
+ adj
] & 0xE0) >> 5);
676 bc
[3] = ((dv
[index
] & 0x1F) << 3) | ((dv
[index
+ adj
] & 0xE0) >> 5);
680 TTCN_EncDec_ErrorContext::error_internal("Invalid FLOAT length %d", length
);
682 return myleaf
.length
= p_td
.raw
->fieldlength
;
685 int FLOAT::RAW_decode(const TTCN_Typedescriptor_t
& p_td
, TTCN_Buffer
& buff
,
686 int limit
, raw_order_t top_bit_ord
, boolean no_err
, int /*sel_field*/,
687 boolean
/*first_call*/)
689 int prepaddlength
= buff
.increase_pos_padd(p_td
.raw
->prepadding
);
691 limit
-= prepaddlength
;
692 int decode_length
= p_td
.raw
->fieldlength
;
693 if ( p_td
.raw
->fieldlength
> limit
694 || p_td
.raw
->fieldlength
> (int) buff
.unread_len_bit()) {
695 if (no_err
) return -1;
696 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_LEN_ERR
,
697 "There is not enough bits in the buffer to decode type %s.", p_td
.name
);
698 decode_length
= limit
> (int) buff
.unread_len_bit()
699 ? buff
.unread_len_bit() : limit
;
702 decode_length
+= buff
.increase_pos_padd(p_td
.raw
->padding
);
703 return decode_length
+ prepaddlength
;
706 unsigned char data
[16];
708 boolean orders
= FALSE
;
709 if (p_td
.raw
->bitorderinoctet
== ORDER_MSB
) orders
= TRUE
;
710 if (p_td
.raw
->bitorderinfield
== ORDER_MSB
) orders
= !orders
;
711 cp
.bitorder
= orders
? ORDER_MSB
: ORDER_LSB
;
713 if (p_td
.raw
->byteorder
== ORDER_MSB
) orders
= TRUE
;
714 if (p_td
.raw
->bitorderinfield
== ORDER_MSB
) orders
= !orders
;
715 cp
.byteorder
= orders
? ORDER_MSB
: ORDER_LSB
;
716 cp
.fieldorder
= p_td
.raw
->fieldorder
;
717 cp
.hexorder
= ORDER_LSB
;
718 buff
.get_b((size_t) decode_length
, data
, cp
, top_bit_ord
);
719 if (decode_length
== 64) {
720 dv
= (unsigned char *) &tmp
;
721 #if defined __sparc__ || defined __sparc
724 for (int i
= 0, k
= 7; i
< 8; i
++, k
--) dv
[i
] = data
[k
];
727 if (no_err
) return -1;
728 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_LEN_ERR
,
729 "Not a Number received for type %s.", p_td
.name
);
733 else if (decode_length
== 32) {
734 int sign
= (data
[0] & 0x80) >> 7;
735 int exponent
= ((data
[0] & 0x7F) << 1) | ((data
[1] & 0x80) >> 7);
736 int fraction
= ((data
[1] & 0x7F) << 1) | ((data
[2] & 0x80) >> 7);
738 fraction
+= ((data
[2] & 0x7F) << 1) | ((data
[3] & 0x80) >> 7);
740 fraction
+= data
[3] & 0x7F;
741 if (exponent
== 0 && fraction
== 0) tmp
= sign
? -0.0 : 0.0;
742 else if (exponent
== 0xFF && fraction
!= 0) {
743 if (no_err
) return -1;
744 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_LEN_ERR
,
745 "Not a Number received for type %s.", p_td
.name
);
748 else if (exponent
== 0 && fraction
!= 0) {
749 double sign_v
= sign
? -1.0 : 1.0;
750 tmp
= sign_v
* (static_cast<double> (fraction
) / 8388608.0)
754 double sign_v
= sign
? -1.0 : 1.0;
756 tmp
= sign_v
* (1.0 + static_cast<double> (fraction
) / 8388608.0)
757 * pow(2.0, static_cast<double> (exponent
));
761 decode_length
+= buff
.increase_pos_padd(p_td
.raw
->padding
);
764 return decode_length
+ prepaddlength
;
767 int FLOAT::XER_encode(const XERdescriptor_t
& p_td
,
768 TTCN_Buffer
& p_buf
, unsigned int flavor
, int indent
, embed_values_enc_struct_t
*) const
771 TTCN_EncDec_ErrorContext::error(
772 TTCN_EncDec::ET_UNBOUND
, "Encoding an unbound float value.");
774 int exer
= is_exer(flavor
|= SIMPLE_TYPE
);
775 // SIMPLE_TYPE has no influence on is_exer, we set it for later
776 int encoded_length
=(int)p_buf
.get_len();
777 flavor
&= ~XER_RECOF
; // float doesn't care
779 begin_xml(p_td
, p_buf
, flavor
, indent
, false);
781 if (exer
&& (p_td
.xer_bits
& XER_DECIMAL
)) {
783 int n
= snprintf(buf
, sizeof(buf
), "%f", (double)float_value
);
784 p_buf
.put_s((size_t)n
, (const unsigned char*)buf
);
787 CHARSTRING value
= float2str(float_value
);
788 p_buf
.put_string(value
);
791 end_xml(p_td
, p_buf
, flavor
, indent
, false);
793 return (int)p_buf
.get_len() - encoded_length
;
796 int FLOAT::XER_decode(const XERdescriptor_t
& p_td
, XmlReaderWrap
& reader
,
797 unsigned int flavor
, embed_values_dec_struct_t
*)
799 int exer
= is_exer(flavor
);
800 int success
= reader
.Ok(), depth
= -1;
801 if (success
<= 0) return 0;
802 boolean own_tag
= !(exer
&& (p_td
.xer_bits
& UNTAGGED
)) && !is_exerlist(flavor
);
804 if (!own_tag
) goto tagless
;
805 if (exer
&& (p_td
.xer_bits
& XER_ATTRIBUTE
)) {
806 verify_name(reader
, p_td
, exer
);
808 const char * value
= (const char *)reader
.Value();
810 if (value
&& sscanf(value
, "%lf", &float_value
))
813 // Let the caller do reader.AdvanceAttribute();
816 for (; success
== 1; success
= reader
.Read()) {
817 int type
= reader
.NodeType();
818 if (XML_READER_TYPE_ELEMENT
== type
) {
819 verify_name(reader
, p_td
, exer
);
820 if (reader
.IsEmptyElement()) {
821 if (exer
&& p_td
.dfeValue
!= 0) {
822 *this = *static_cast<const FLOAT
*>(p_td
.dfeValue
);
827 depth
= reader
.Depth();
829 else if (XML_READER_TYPE_TEXT
== type
&& depth
!= -1) {
830 const char * value
= (const char*)reader
.Value();
831 if (value
&& sscanf(value
, "%lf", &float_value
) == 1)
834 else if (XML_READER_TYPE_END_ELEMENT
== type
) {
835 verify_end(reader
, p_td
, depth
, exer
);
836 if (!bound_flag
&& exer
&& p_td
.dfeValue
!= 0) {
837 *this = *static_cast<const FLOAT
*>(p_td
.dfeValue
);
843 } // if not attribute
844 return 1; // decode successful
847 const char* POS_INF_STR
= "\"infinity\"";
848 const char* NEG_INF_STR
= "\"-infinity\"";
849 const char* NAN_STR
= "\"not_a_number\"";
851 int FLOAT::JSON_encode(const TTCN_Typedescriptor_t
&, JSON_Tokenizer
& p_tok
) const
854 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND
,
855 "Encoding an unbound float value.");
859 double value
= (double)float_value
;
860 if ((double)INFINITY
== value
) {
861 return p_tok
.put_next_token(JSON_TOKEN_STRING
, POS_INF_STR
);
863 if (-(double)INFINITY
== value
) {
864 return p_tok
.put_next_token(JSON_TOKEN_STRING
, NEG_INF_STR
);
867 return p_tok
.put_next_token(JSON_TOKEN_STRING
, NAN_STR
);
870 // true if decimal representation possible (use %f format)
871 bool decimal_repr
= (value
== 0.0)
872 || (value
> -MAX_DECIMAL_FLOAT
&& value
<= -MIN_DECIMAL_FLOAT
)
873 || (value
>= MIN_DECIMAL_FLOAT
&& value
< MAX_DECIMAL_FLOAT
);
875 char* tmp_str
= mprintf(decimal_repr
? "%f" : "%e", value
);
876 int enc_len
= p_tok
.put_next_token(JSON_TOKEN_NUMBER
, tmp_str
);
881 int FLOAT::JSON_decode(const TTCN_Typedescriptor_t
& p_td
, JSON_Tokenizer
& p_tok
, boolean p_silent
)
884 json_token_t token
= JSON_TOKEN_NONE
;
886 size_t value_len
= 0;
888 boolean use_default
= p_td
.json
->default_value
&& 0 == p_tok
.get_buffer_length();
890 // No JSON data in the buffer -> use default value
891 value
= (char*)p_td
.json
->default_value
;
892 value_len
= strlen(value
);
894 dec_len
= p_tok
.get_next_token(&token
, &value
, &value_len
);
896 if (JSON_TOKEN_ERROR
== token
) {
897 JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG
, JSON_DEC_BAD_TOKEN_ERROR
, "");
898 return JSON_ERROR_FATAL
;
900 else if (JSON_TOKEN_STRING
== token
|| use_default
) {
901 if (0 == strncmp(value
, POS_INF_STR
+ (use_default
? 1 : 0), value_len
)) {
903 float_value
= INFINITY
;
905 else if (0 == strncmp(value
, NEG_INF_STR
+ (use_default
? 1 : 0), value_len
)) {
907 float_value
= -INFINITY
;
909 else if (0 == strncmp(value
, NAN_STR
+ (use_default
? 1 : 0), value_len
)) {
914 float_value
= INFINITY
+ (-INFINITY
);
917 else if (!use_default
) {
918 char* spec_val
= mprintf("float (%s, %s or %s)", POS_INF_STR
, NEG_INF_STR
, NAN_STR
);
919 JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG
, JSON_DEC_FORMAT_ERROR
, "string", spec_val
);
922 return JSON_ERROR_FATAL
;
925 else if (JSON_TOKEN_NUMBER
== token
) {
926 char* value2
= mcopystrn(value
, value_len
);
927 sscanf(value2
, "%lf", &float_value
);
931 return JSON_ERROR_INVALID_TOKEN
;
933 if (!bound_flag
&& use_default
) {
934 // Already checked the default value for the string possibilities, now
935 // check for a valid number
936 char* value2
= mcopystrn(value
, value_len
);
937 sscanf(value2
, "%lf", &float_value
);
947 double operator+(double double_value
, const FLOAT
& other_value
)
949 other_value
.must_bound("Unbound right operand of float addition.");
950 FLOAT::check_numeric(double_value
, "Left operand of float addition");
951 FLOAT::check_numeric(other_value
.float_value
, "Right operand of float addition");
952 return double_value
+ other_value
.float_value
;
955 double operator-(double double_value
, const FLOAT
& other_value
)
957 other_value
.must_bound("Unbound right operand of float subtraction.");
958 FLOAT::check_numeric(double_value
, "Left operand of float subtraction");
959 FLOAT::check_numeric(other_value
.float_value
, "Right operand of float subtraction");
960 return double_value
- other_value
.float_value
;
963 double operator*(double double_value
, const FLOAT
& other_value
)
965 other_value
.must_bound("Unbound right operand of float multiplication.");
966 FLOAT::check_numeric(double_value
, "Left operand of float multiplication");
967 FLOAT::check_numeric(other_value
.float_value
, "Right operand of float multiplication");
968 return double_value
* other_value
.float_value
;
971 double operator/(double double_value
, const FLOAT
& other_value
)
973 other_value
.must_bound("Unbound right operand of float division.");
974 FLOAT::check_numeric(double_value
, "Left operand of float division");
975 FLOAT::check_numeric(other_value
.float_value
, "Right operand of float division");
976 if (other_value
.float_value
== 0.0) TTCN_error("Float division by zero.");
977 return double_value
/ other_value
.float_value
;
980 boolean
operator==(double double_value
, const FLOAT
& other_value
)
982 other_value
.must_bound("Unbound right operand of float comparison.");
983 return double_value
== other_value
.float_value
;
986 boolean
operator<(double double_value
, const FLOAT
& other_value
)
988 other_value
.must_bound("Unbound right operand of float comparison.");
989 return double_value
< other_value
.float_value
;
992 boolean
operator>(double double_value
, const FLOAT
& other_value
)
994 other_value
.must_bound("Unbound right operand of float comparison.");
995 return double_value
> other_value
.float_value
;
998 // float template class
1000 void FLOAT_template::clean_up()
1002 if (template_selection
== VALUE_LIST
||
1003 template_selection
== COMPLEMENTED_LIST
)
1004 delete [] value_list
.list_value
;
1005 template_selection
= UNINITIALIZED_TEMPLATE
;
1008 void FLOAT_template::copy_template(const FLOAT_template
& other_value
)
1010 switch (other_value
.template_selection
) {
1011 case SPECIFIC_VALUE
:
1012 single_value
= other_value
.single_value
;
1019 case COMPLEMENTED_LIST
:
1020 value_list
.n_values
= other_value
.value_list
.n_values
;
1021 value_list
.list_value
= new FLOAT_template
[value_list
.n_values
];
1022 for (unsigned int i
= 0; i
< value_list
.n_values
; i
++)
1023 value_list
.list_value
[i
].copy_template(
1024 other_value
.value_list
.list_value
[i
]);
1027 value_range
= other_value
.value_range
;
1030 TTCN_error("Copying an uninitialized/unsupported float template.");
1032 set_selection(other_value
);
1035 FLOAT_template::FLOAT_template()
1040 FLOAT_template::FLOAT_template(template_sel other_value
)
1041 : Base_Template(other_value
)
1043 check_single_selection(other_value
);
1046 FLOAT_template::FLOAT_template(double other_value
)
1047 : Base_Template(SPECIFIC_VALUE
)
1049 single_value
= other_value
;
1052 FLOAT_template::FLOAT_template(const FLOAT
& other_value
)
1053 : Base_Template(SPECIFIC_VALUE
)
1055 other_value
.must_bound("Creating a template from an unbound float value.");
1056 single_value
= other_value
.float_value
;
1059 FLOAT_template::FLOAT_template(const OPTIONAL
<FLOAT
>& other_value
)
1061 switch (other_value
.get_selection()) {
1062 case OPTIONAL_PRESENT
:
1063 set_selection(SPECIFIC_VALUE
);
1064 single_value
= (double)(const FLOAT
&)other_value
;
1067 set_selection(OMIT_VALUE
);
1070 TTCN_error("Creating a float template from an unbound optional field.");
1074 FLOAT_template::FLOAT_template(const FLOAT_template
& other_value
)
1077 copy_template(other_value
);
1080 FLOAT_template::~FLOAT_template()
1085 FLOAT_template
& FLOAT_template::operator=(template_sel other_value
)
1087 check_single_selection(other_value
);
1089 set_selection(other_value
);
1093 FLOAT_template
& FLOAT_template::operator=(double other_value
)
1096 set_selection(SPECIFIC_VALUE
);
1097 single_value
= other_value
;
1101 FLOAT_template
& FLOAT_template::operator=(const FLOAT
& other_value
)
1103 other_value
.must_bound("Assignment of an unbound float value "
1106 set_selection(SPECIFIC_VALUE
);
1107 single_value
= other_value
.float_value
;
1111 FLOAT_template
& FLOAT_template::operator=(const OPTIONAL
<FLOAT
>& other_value
)
1114 switch (other_value
.get_selection()) {
1115 case OPTIONAL_PRESENT
:
1116 set_selection(SPECIFIC_VALUE
);
1117 single_value
= (double)(const FLOAT
&)other_value
;
1120 set_selection(OMIT_VALUE
);
1123 TTCN_error("Assignment of an unbound optional field to a float template.");
1128 FLOAT_template
& FLOAT_template::operator=(const FLOAT_template
& other_value
)
1130 if (&other_value
!= this) {
1132 copy_template(other_value
);
1137 boolean
FLOAT_template::match(double other_value
) const
1139 switch (template_selection
) {
1140 case SPECIFIC_VALUE
:
1141 return single_value
== other_value
;
1148 case COMPLEMENTED_LIST
:
1149 for (unsigned int i
= 0; i
< value_list
.n_values
; i
++)
1150 if(value_list
.list_value
[i
].match(other_value
))
1151 return template_selection
== VALUE_LIST
;
1152 return template_selection
== COMPLEMENTED_LIST
;
1154 return (!value_range
.min_is_present
||
1155 value_range
.min_value
<= other_value
) &&
1156 (!value_range
.max_is_present
||
1157 value_range
.max_value
>= other_value
);
1159 TTCN_error("Matching with an uninitialized/unsupported float template.");
1164 boolean
FLOAT_template::match(const FLOAT
& other_value
) const
1166 if (!other_value
.is_bound()) return FALSE
;
1167 return match(other_value
.float_value
);
1171 void FLOAT_template::set_type(template_sel template_type
,
1172 unsigned int list_length
)
1175 switch (template_type
) {
1177 case COMPLEMENTED_LIST
:
1178 set_selection(template_type
);
1179 value_list
.n_values
= list_length
;
1180 value_list
.list_value
= new FLOAT_template
[list_length
];
1183 set_selection(VALUE_RANGE
);
1184 value_range
.min_is_present
= FALSE
;
1185 value_range
.max_is_present
= FALSE
;
1188 TTCN_error("Setting an invalid type for a float template.");
1192 FLOAT_template
& FLOAT_template::list_item(unsigned int list_index
)
1194 if (template_selection
!= VALUE_LIST
&&
1195 template_selection
!= COMPLEMENTED_LIST
)
1196 TTCN_error("Accessing a list element of a non-list float template.");
1197 if (list_index
>= value_list
.n_values
)
1198 TTCN_error("Index overflow in a float value list template.");
1199 return value_list
.list_value
[list_index
];
1202 void FLOAT_template::set_min(double min_value
)
1204 if (template_selection
!= VALUE_RANGE
)
1205 TTCN_error("Float template is not range when setting lower limit.");
1206 if (value_range
.max_is_present
&& value_range
.max_value
< min_value
)
1207 TTCN_error("The lower limit of the range is greater than the "
1208 "upper limit in a float template.");
1209 value_range
.min_is_present
= TRUE
;
1210 value_range
.min_value
= min_value
;
1213 void FLOAT_template::set_min(const FLOAT
& min_value
)
1215 min_value
.must_bound("Using an unbound value when setting the lower bound "
1216 "in a float range template.");
1217 set_min(min_value
.float_value
);
1220 void FLOAT_template::set_max(double max_value
)
1222 if (template_selection
!= VALUE_RANGE
)
1223 TTCN_error("Float template is not range when setting upper limit.");
1224 if (value_range
.min_is_present
&& value_range
.min_value
> max_value
)
1225 TTCN_error("The upper limit of the range is smaller than the "
1226 "lower limit in a float template.");
1227 value_range
.max_is_present
= TRUE
;
1228 value_range
.max_value
= max_value
;
1231 void FLOAT_template::set_max(const FLOAT
& max_value
)
1233 max_value
.must_bound("Using an unbound value when setting the upper bound "
1234 "in a float range template.");
1235 set_max(max_value
.float_value
);
1238 double FLOAT_template::valueof() const
1240 if (template_selection
!= SPECIFIC_VALUE
|| is_ifpresent
)
1241 TTCN_error("Performing a valueof "
1242 "or send operation on a non-specific float template.");
1243 return single_value
;
1246 void FLOAT_template::log() const
1248 switch (template_selection
) {
1249 case SPECIFIC_VALUE
:
1250 log_float(single_value
);
1252 case COMPLEMENTED_LIST
:
1253 TTCN_Logger::log_event_str("complement ");
1256 TTCN_Logger::log_char('(');
1257 for (unsigned int i
= 0; i
< value_list
.n_values
; i
++) {
1258 if (i
> 0) TTCN_Logger::log_event_str(", ");
1259 value_list
.list_value
[i
].log();
1261 TTCN_Logger::log_char(')');
1264 TTCN_Logger::log_char('(');
1265 if (value_range
.min_is_present
) log_float(value_range
.min_value
);
1266 else TTCN_Logger::log_event_str("-infinity");
1267 TTCN_Logger::log_event_str(" .. ");
1268 if (value_range
.max_is_present
) log_float(value_range
.max_value
);
1269 else TTCN_Logger::log_event_str("infinity");
1270 TTCN_Logger::log_char(')');
1279 void FLOAT_template::log_match(const FLOAT
& match_value
) const
1281 if (TTCN_Logger::VERBOSITY_COMPACT
== TTCN_Logger::get_matching_verbosity()
1282 && TTCN_Logger::get_logmatch_buffer_len() != 0) {
1283 TTCN_Logger::print_logmatch_buffer();
1284 TTCN_Logger::log_event_str(" := ");
1287 TTCN_Logger::log_event_str(" with ");
1289 if (match(match_value
)) TTCN_Logger::log_event_str(" matched");
1290 else TTCN_Logger::log_event_str(" unmatched");
1293 void FLOAT_template::set_param(Module_Param
& param
) {
1294 param
.basic_check(Module_Param::BC_TEMPLATE
, "float template");
1295 switch (param
.get_type()) {
1296 case Module_Param::MP_Omit
:
1299 case Module_Param::MP_Any
:
1302 case Module_Param::MP_AnyOrNone
:
1303 *this = ANY_OR_OMIT
;
1305 case Module_Param::MP_List_Template
:
1306 case Module_Param::MP_ComplementList_Template
:
1307 set_type(param
.get_type()==Module_Param::MP_List_Template
? VALUE_LIST
: COMPLEMENTED_LIST
, param
.get_size());
1308 for (size_t i
=0; i
<param
.get_size(); i
++) {
1309 list_item(i
).set_param(*param
.get_elem(i
));
1312 case Module_Param::MP_Float
:
1313 *this = param
.get_float();
1315 case Module_Param::MP_FloatRange
:
1316 set_type(VALUE_RANGE
);
1317 if (param
.has_lower_float()) set_min(param
.get_lower_float());
1318 if (param
.has_upper_float()) set_max(param
.get_upper_float());
1321 param
.type_error("float template");
1323 is_ifpresent
= param
.get_ifpresent();
1326 void FLOAT_template::encode_text(Text_Buf
& text_buf
) const
1328 encode_text_base(text_buf
);
1329 switch (template_selection
) {
1334 case SPECIFIC_VALUE
:
1335 text_buf
.push_double(single_value
);
1338 case COMPLEMENTED_LIST
:
1339 text_buf
.push_int(value_list
.n_values
);
1340 for (unsigned int i
= 0; i
< value_list
.n_values
; i
++)
1341 value_list
.list_value
[i
].encode_text(text_buf
);
1344 text_buf
.push_int(value_range
.min_is_present
? 1 : 0);
1345 if (value_range
.min_is_present
)
1346 text_buf
.push_double(value_range
.min_value
);
1347 text_buf
.push_int(value_range
.max_is_present
? 1 : 0);
1348 if (value_range
.max_is_present
)
1349 text_buf
.push_double(value_range
.max_value
);
1352 TTCN_error("Text encoder: Encoding an undefined/unsupported "
1357 void FLOAT_template::decode_text(Text_Buf
& text_buf
)
1360 decode_text_base(text_buf
);
1361 switch (template_selection
) {
1366 case SPECIFIC_VALUE
:
1367 single_value
= text_buf
.pull_double();
1370 case COMPLEMENTED_LIST
:
1371 value_list
.n_values
= text_buf
.pull_int().get_val();
1372 value_list
.list_value
= new FLOAT_template
[value_list
.n_values
];
1373 for (unsigned int i
= 0; i
< value_list
.n_values
; i
++)
1374 value_list
.list_value
[i
].decode_text(text_buf
);
1377 value_range
.min_is_present
= text_buf
.pull_int() != 0;
1378 if (value_range
.min_is_present
)
1379 value_range
.min_value
= text_buf
.pull_double();
1380 value_range
.max_is_present
= text_buf
.pull_int() != 0;
1381 if (value_range
.max_is_present
)
1382 value_range
.max_value
= text_buf
.pull_double();
1385 TTCN_error("Text decoder: An unknown/unsupported selection was "
1386 "received for a float template.");
1390 boolean
FLOAT_template::is_present() const
1392 if (template_selection
==UNINITIALIZED_TEMPLATE
) return FALSE
;
1393 return !match_omit();
1396 boolean
FLOAT_template::match_omit() const
1398 if (is_ifpresent
) return TRUE
;
1399 switch (template_selection
) {
1404 case COMPLEMENTED_LIST
:
1405 for (unsigned int i
=0; i
<value_list
.n_values
; i
++)
1406 if (value_list
.list_value
[i
].match_omit())
1407 return template_selection
==VALUE_LIST
;
1408 return template_selection
==COMPLEMENTED_LIST
;
1415 #ifndef TITAN_RUNTIME_2
1416 void FLOAT_template::check_restriction(template_res t_res
, const char* t_name
) const
1418 if (template_selection
==UNINITIALIZED_TEMPLATE
) return;
1419 switch ((t_name
&&(t_res
==TR_VALUE
))?TR_OMIT
:t_res
) {
1421 if (!is_ifpresent
&& template_selection
==SPECIFIC_VALUE
) return;
1424 if (!is_ifpresent
&& (template_selection
==OMIT_VALUE
||
1425 template_selection
==SPECIFIC_VALUE
)) return;
1428 if (!match_omit()) return;
1433 TTCN_error("Restriction `%s' on template of type %s violated.",
1434 get_res_name(t_res
), t_name
? t_name
: "float");