Sync with 5.2.0
[deliverable/titan.core.git] / core / Float.cc
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 ///////////////////////////////////////////////////////////////////////////////
8 #include <string.h>
9 #include <math.h>
10 #include <float.h>
11
12 #include "../common/memory.h"
13 #include "Float.hh"
14 #include "Types.h"
15 #include "Param_Types.hh"
16 #include "Optional.hh"
17 #include "Logger.hh"
18 #include "Error.hh"
19 #include "Encdec.hh"
20 #include "RAW.hh"
21 #include "BER.hh"
22 #include "Charstring.hh"
23 #include "Addfunc.hh"
24 #include "XmlReader.hh"
25
26 #include "../common/dbgnew.hh"
27
28
29 #ifndef INFINITY
30 #define INFINITY (DBL_MAX*DBL_MAX)
31 #endif
32 const FLOAT PLUS_INFINITY(INFINITY);
33 const FLOAT MINUS_INFINITY(-INFINITY);
34
35 #ifdef NAN
36 const FLOAT NOT_A_NUMBER(NAN);
37 #else
38 const FLOAT NOT_A_NUMBER((double)PLUS_INFINITY+(double)MINUS_INFINITY);
39 // The casts ensure that FLOAT::operator+ is not called
40 #endif
41
42
43 static inline void log_float(double float_val)
44 {
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);
56 }
57
58 // float value class
59
60 FLOAT::FLOAT()
61 {
62 bound_flag = FALSE;
63 }
64
65 FLOAT::FLOAT(double other_value)
66 {
67 bound_flag = TRUE;
68 float_value = other_value;
69 }
70
71 FLOAT::FLOAT(const FLOAT& other_value)
72 : Base_Type(other_value)
73 {
74 other_value.must_bound("Copying an unbound float value.");
75 bound_flag = TRUE;
76 float_value = other_value.float_value;
77 }
78
79 void FLOAT::clean_up()
80 {
81 bound_flag = FALSE;
82 }
83
84 FLOAT& FLOAT::operator=(double other_value)
85 {
86 bound_flag = TRUE;
87 float_value = other_value;
88 return *this;
89 }
90
91 FLOAT& FLOAT::operator=(const FLOAT& other_value)
92 {
93 other_value.must_bound("Assignment of an unbound float value.");
94 bound_flag = TRUE;
95 float_value = other_value.float_value;
96 return *this;
97 }
98
99 double FLOAT::operator+() const
100 {
101 must_bound("Unbound float operand of unary + operator.");
102 return float_value;
103 }
104
105 double FLOAT::operator-() const
106 {
107 must_bound("Unbound float operand of unary - operator (negation).");
108 return -float_value;
109 }
110
111 bool FLOAT::is_special(double flt_val)
112 {
113 return ( (flt_val!=flt_val) || (flt_val==INFINITY) || (flt_val==-INFINITY) );
114 }
115
116 void FLOAT::check_numeric(double flt_val, const char *err_msg_begin)
117 {
118 if (is_special(flt_val)) {
119 TTCN_error("%s must be a numeric value instead of %g",
120 err_msg_begin, flt_val);
121 }
122 }
123
124 double FLOAT::operator+(double other_value) const
125 {
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;
130 }
131
132 double FLOAT::operator+(const FLOAT& other_value) const
133 {
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;
139 }
140
141 double FLOAT::operator-(double other_value) const
142 {
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;
147 }
148
149 double FLOAT::operator-(const FLOAT& other_value) const
150 {
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;
156 }
157
158 double FLOAT::operator*(double other_value) const
159 {
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;
164 }
165
166 double FLOAT::operator*(const FLOAT& other_value) const
167 {
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;
173 }
174
175 double FLOAT::operator/(double other_value) const
176 {
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;
182 }
183
184 double FLOAT::operator/(const FLOAT& other_value) const
185 {
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;
192 }
193
194 boolean FLOAT::operator==(double other_value) const
195 {
196 must_bound("Unbound left operand of float comparison.");
197 return float_value == other_value;
198 }
199
200 boolean FLOAT::operator==(const FLOAT& other_value) const
201 {
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;
205 }
206
207 boolean FLOAT::operator<(double other_value) const
208 {
209 must_bound("Unbound left operand of float comparison.");
210 return float_value < other_value;
211 }
212
213 boolean FLOAT::operator<(const FLOAT& other_value) const
214 {
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;
218 }
219
220 boolean FLOAT::operator>(double other_value) const
221 {
222 must_bound("Unbound left operand of float comparison.");
223 return float_value > other_value;
224 }
225
226 boolean FLOAT::operator>(const FLOAT& other_value) const
227 {
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;
231 }
232
233 FLOAT::operator double() const
234 {
235 must_bound("Using the value of an unbound float variable.");
236 return float_value;
237 }
238
239 void FLOAT::log() const
240 {
241 if (bound_flag) log_float(float_value);
242 else TTCN_Logger::log_event_unbound();
243 }
244
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");
248 bound_flag = TRUE;
249 float_value = param.get_float();
250 }
251
252 void FLOAT::encode_text(Text_Buf& text_buf) const
253 {
254 must_bound("Text encoder: Encoding an unbound float value.");
255 text_buf.push_double(float_value);
256 }
257
258 void FLOAT::decode_text(Text_Buf& text_buf)
259 {
260 bound_flag = TRUE;
261 float_value = text_buf.pull_double();
262 }
263
264 void FLOAT::encode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf,
265 TTCN_EncDec::coding_t p_coding, ...) const
266 {
267 va_list pvar;
268 va_start(pvar, p_coding);
269 switch(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);
277 break;}
278 case TTCN_EncDec::CT_RAW: {
279 TTCN_EncDec_ErrorContext ec("While RAW-encoding type '%s': ", p_td.name);
280 if(!p_td.raw)
281 TTCN_EncDec_ErrorContext::error_internal
282 ("No RAW descriptor available for type '%s'.", p_td.name);
283 RAW_enc_tr_pos rp;
284 rp.level=0;
285 rp.pos=NULL;
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);
289 break;}
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);
294 break;}
295 case TTCN_EncDec::CT_JSON: {
296 TTCN_EncDec_ErrorContext ec("While JSON-encoding type '%s': ", p_td.name);
297 if(!p_td.json)
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());
303 break;}
304 default:
305 TTCN_error("Unknown coding method requested to encode type '%s'",
306 p_td.name);
307 }
308 va_end(pvar);
309 }
310
311 void FLOAT::decode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf,
312 TTCN_EncDec::coding_t p_coding, ...)
313 {
314 va_list pvar;
315 va_start(pvar, p_coding);
316 switch(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);
320 ASN_BER_TLV_t tlv;
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());
324 break;}
325 case TTCN_EncDec::CT_RAW: {
326 TTCN_EncDec_ErrorContext ec("While RAW-decoding type '%s': ", p_td.name);
327 if(!p_td.raw)
328 TTCN_EncDec_ErrorContext::error_internal
329 ("No RAW descriptor available for type '%s'.", p_td.name);
330 raw_order_t order;
331 switch(p_td.raw->top_bit_order){
332 case TOP_BIT_LEFT:
333 order=ORDER_LSB;
334 break;
335 case TOP_BIT_RIGHT:
336 default:
337 order=ORDER_MSB;
338 }
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"
343 , p_td.name);
344 break;}
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)
352 break;
353 }
354 XER_decode(*p_td.xer, reader, XER_coding, 0);
355 size_t bytes = reader.ByteConsumed();
356 p_buf.set_pos(bytes);
357 break;}
358 case TTCN_EncDec::CT_JSON: {
359 TTCN_EncDec_ErrorContext ec("While JSON-decoding type '%s': ", p_td.name);
360 if(!p_td.json)
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"
368 , p_td.name);
369 p_buf.set_pos(tok.get_buf_pos());
370 break;}
371 default:
372 TTCN_error("Unknown coding method requested to decode type '%s'",
373 p_td.name);
374 }
375 va_end(pvar);
376 }
377
378 ASN_BER_TLV_t*
379 FLOAT::BER_encode_TLV(const TTCN_Typedescriptor_t& p_td,
380 unsigned p_coding) const
381 {
382 BER_chk_descr(p_td);
383 ASN_BER_TLV_t *new_tlv=BER_encode_chk_bound(is_bound());
384 if(!new_tlv) {
385 if(float_value==0.0) {
386 new_tlv=ASN_BER_TLV_t::construct();
387 // nothing to do, Vlen is 0
388 }
389 /* +Infinity */
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;
393 }
394 /* -Infinity */
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;
398 }
399 else if(isnan((double)float_value)) {
400 TTCN_EncDec_ErrorContext::error_internal("Value is NaN.");
401 }
402 else {
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;
408 /** \todo review
409 gcc 2.95:
410 in mprintf below:
411 warning: `.' not followed by `*' or digit in format
412 */
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]);
416 }
417 }
418 new_tlv=ASN_BER_V2TLV(new_tlv, p_td, p_coding);
419 return new_tlv;
420 }
421
422 boolean FLOAT::BER_decode_TLV(const TTCN_Typedescriptor_t& p_td,
423 const ASN_BER_TLV_t& p_tlv,
424 unsigned L_form)
425 {
426 bound_flag = FALSE;
427 BER_chk_descr(p_td);
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;
435 if(Vlen==0) {
436 float_value=0.0;
437 }
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"
442 " supported.");
443 float_value=0.0;
444 }
445 else if(Vstr[0] & 0x40) {
446 /* SpecialRealValue */
447 if(Vlen>1)
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).");
451 if(Vstr[0] & 0x3E)
452 ec.error(TTCN_EncDec::ET_INVAL_MSG,
453 "This is a reserved value: 0x%x (See X.690 8.5.8).",
454 Vstr[0]);
455 if(Vstr[0] & 0x01)
456 /* MINUS-INFINITY */
457 float_value=-INFINITY;
458 else
459 /* PLUS-INFINITY */
460 float_value=INFINITY;
461 }
462 else {
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).",
467 Vstr[0]);
468 int NR=Vstr[0] & 0x03; // which NumericalRepresentation
469 boolean
470 leadingzero=FALSE,
471 NR_error=FALSE;
472 unsigned char
473 *Vstr_last=Vstr+Vlen-1,
474 *sign=NULL,
475 *mant1=NULL,
476 *decmark=NULL,
477 *mant2=NULL,
478 *expmark=NULL,
479 *expsign=NULL,
480 *expo=NULL,
481 *ptr=Vstr+1;
482 size_t
483 mant1_len=0,
484 mant2_len=0,
485 expo_len=0;
486 long exponum;
487 if(Vlen==1) goto dec_error;
488 while(*ptr==' ') {
489 if(ptr==Vstr_last) goto dec_error;
490 ptr++;
491 }
492 if(*ptr=='+' || *ptr=='-') {
493 sign=ptr;
494 if(ptr==Vstr_last) goto dec_error;
495 ptr++;
496 }
497 while(*ptr=='0') {
498 leadingzero=TRUE;
499 if(ptr==Vstr_last) goto str_end;
500 ptr++;
501 }
502 while(*ptr>='0' && *ptr<='9') {
503 if(mant1_len==0) mant1=ptr;
504 mant1_len++;
505 if(ptr==Vstr_last) goto str_end;
506 ptr++;
507 }
508 if(*ptr=='.' || *ptr==',') {
509 decmark=ptr;
510 if(ptr==Vstr_last) goto str_end;
511 ptr++;
512 }
513 while(*ptr>='0' && *ptr<='9') {
514 if(mant2_len==0) mant2=ptr;
515 mant2_len++;
516 if(ptr==Vstr_last) goto str_end;
517 ptr++;
518 }
519 if(!leadingzero && !mant1 && !mant2) goto dec_error;
520 if(*ptr=='e' || *ptr=='E') {
521 expmark=ptr;
522 if(ptr==Vstr_last) goto dec_error;
523 ptr++;
524 }
525 if(*ptr=='+' || *ptr=='-') {
526 expsign=ptr;
527 if(ptr==Vstr_last) goto dec_error;
528 ptr++;
529 }
530 while(*ptr=='0') {
531 expo=ptr;
532 if(ptr==Vstr_last) goto str_end;
533 ptr++;
534 }
535 while(*ptr>='0' && *ptr<='9') {
536 if(expo_len==0) expo=ptr;
537 expo_len++;
538 if(ptr==Vstr_last) goto str_end;
539 ptr++;
540 }
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.");
545 str_end:
546 /* check NR */
547 if(NR==1) {
548 if(decmark || expmark) NR_error=TRUE;
549 }
550 else if(NR==2) {
551 if(expmark) NR_error=TRUE;
552 }
553 if(NR_error)
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;
558 float_value=0.0;
559 if(mant1) for(size_t i=0; i<mant1_len; i++) {
560 float_value*=10.0;
561 float_value+=static_cast<double>(mant1[i]-'0');
562 } // for i if...
563 if(mant2) for(size_t i=0; i<mant2_len; i++) {
564 float_value*=10.0;
565 float_value+=static_cast<double>(mant2[i]-'0');
566 } // for i if...
567 exponum=0;
568 if(expo) {
569 if(ceil(log10(log10(DBL_MAX)))<expo_len) {
570 /* overflow */
571 if(expsign && *expsign=='-') {
572 float_value=0.0;
573 }
574 else {
575 if(sign && *sign=='-') float_value=-INFINITY;
576 else float_value=INFINITY;
577 }
578 goto end;
579 } // overflow
580 else {
581 /* no overflow */
582 for(size_t i=0; i<expo_len; i++) {
583 exponum*=10;
584 exponum+=static_cast<int>(expo[i]-'0');
585 } // for i
586 if(expsign && *expsign=='-')
587 exponum*=-1;
588 } // no overflow
589 } // if expo
590 if(mant2) exponum-=mant2_len;
591 float_value*=pow(10.0, static_cast<double>(exponum));
592 goto end;
593 dec_error:
594 ec.error(TTCN_EncDec::ET_INVAL_MSG, "Erroneous decimal encoding.");
595 float_value=0.0;
596 }
597 end:
598 bound_flag=TRUE;
599 return TRUE;
600 }
601
602 int FLOAT::RAW_encode(const TTCN_Typedescriptor_t& p_td, RAW_enc_tree& myleaf) const
603 {
604 unsigned char *bc;
605 unsigned char *dv;
606 int length = p_td.raw->fieldlength / 8;
607 double tmp = float_value;
608 if (!is_bound()) {
609 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND,
610 "Encoding an unbound value.");
611 tmp = 0.0;
612 }
613 if (isnan(tmp)) {
614 TTCN_EncDec_ErrorContext::error_internal("Value is NaN.");
615 }
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;
621 }
622 else {
623 bc = myleaf.body.leaf.data_array;
624 }
625 if (length == 8) {
626 dv = (unsigned char *) &tmp;
627 #if defined __sparc__ || defined __sparc
628 memcpy(bc,dv,8);
629 #else
630 for (int i = 0, k = 7; i < 8; i++, k--) bc[i] = dv[k];
631 #endif
632 }
633 else if (length == 4) {
634 if (tmp == 0.0) memset(bc, 0, 4);
635 else if (tmp == -0.0) {
636 memset(bc, 0, 4);
637 bc[0] |= 0x80;
638 }
639 else {
640 #if defined __sparc__ || defined __sparc
641 int index=0;
642 int adj=1;
643 #else
644 int index = 7;
645 int adj = -1;
646 #endif
647 dv = (unsigned char *) &tmp;
648 bc[0] = dv[index] & 0x80;
649 int exponent = dv[index] & 0x7F;
650 exponent <<= 4;
651 index += adj;
652 exponent += (dv[index] & 0xF0) >> 4;
653 exponent -= 1023;
654
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);
659 tmp = 0.0;
660 exponent = 0;
661 }
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);
666 tmp = 0.0;
667 exponent = 0;
668 }
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);
673 index += adj;
674 bc[2] = ((dv[index] & 0x1F) << 3) | ((dv[index + adj] & 0xE0) >> 5);
675 index += adj;
676 bc[3] = ((dv[index] & 0x1F) << 3) | ((dv[index + adj] & 0xE0) >> 5);
677 }
678 }
679 else
680 TTCN_EncDec_ErrorContext::error_internal("Invalid FLOAT length %d", length);
681
682 return myleaf.length = p_td.raw->fieldlength;
683 }
684
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*/)
688 {
689 int prepaddlength = buff.increase_pos_padd(p_td.raw->prepadding);
690 unsigned char *dv;
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;
700 bound_flag = TRUE;
701 float_value = 0.0;
702 decode_length += buff.increase_pos_padd(p_td.raw->padding);
703 return decode_length + prepaddlength;
704 }
705 double tmp = 0.0;
706 unsigned char data[16];
707 RAW_coding_par cp;
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;
712 orders = FALSE;
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
722 memcpy(dv,data,8);
723 #else
724 for (int i = 0, k = 7; i < 8; i++, k--) dv[i] = data[k];
725 #endif
726 if (isnan(tmp)) {
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);
730 tmp = 0.0;
731 }
732 }
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);
737 fraction <<= 8;
738 fraction += ((data[2] & 0x7F) << 1) | ((data[3] & 0x80) >> 7);
739 fraction <<= 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);
746 tmp = 0.0;
747 }
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)
751 * pow(2.0, -126.0);
752 }
753 else {
754 double sign_v = sign ? -1.0 : 1.0;
755 exponent -= 127;
756 tmp = sign_v * (1.0 + static_cast<double> (fraction) / 8388608.0)
757 * pow(2.0, static_cast<double> (exponent));
758 }
759
760 }
761 decode_length += buff.increase_pos_padd(p_td.raw->padding);
762 bound_flag = TRUE;
763 float_value = tmp;
764 return decode_length + prepaddlength;
765 }
766
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
769 {
770 if(!is_bound()) {
771 TTCN_EncDec_ErrorContext::error(
772 TTCN_EncDec::ET_UNBOUND, "Encoding an unbound float value.");
773 }
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
778
779 begin_xml(p_td, p_buf, flavor, indent, false);
780
781 if (exer && (p_td.xer_bits & XER_DECIMAL)) {
782 char buf[312];
783 int n = snprintf(buf, sizeof(buf), "%f", (double)float_value);
784 p_buf.put_s((size_t)n, (const unsigned char*)buf);
785 }
786 else {
787 CHARSTRING value = float2str(float_value);
788 p_buf.put_string(value);
789 }
790
791 end_xml(p_td, p_buf, flavor, indent, false);
792
793 return (int)p_buf.get_len() - encoded_length;
794 }
795
796 int FLOAT::XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& reader,
797 unsigned int flavor, embed_values_dec_struct_t*)
798 {
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);
803
804 if (!own_tag) goto tagless;
805 if (exer && (p_td.xer_bits & XER_ATTRIBUTE)) {
806 verify_name(reader, p_td, exer);
807 tagless:
808 const char * value = (const char *)reader.Value();
809
810 if (value && sscanf(value, "%lf", &float_value))
811 bound_flag = true;
812
813 // Let the caller do reader.AdvanceAttribute();
814 }
815 else {
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);
823 }
824 reader.Read();
825 break;
826 }
827 depth = reader.Depth();
828 }
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)
832 bound_flag = true;
833 }
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);
838 }
839 reader.Read();
840 break;
841 }
842 } // next read
843 } // if not attribute
844 return 1; // decode successful
845 }
846
847 const char* POS_INF_STR = "\"infinity\"";
848 const char* NEG_INF_STR = "\"-infinity\"";
849 const char* NAN_STR = "\"not_a_number\"";
850
851 int FLOAT::JSON_encode(const TTCN_Typedescriptor_t&, JSON_Tokenizer& p_tok) const
852 {
853 if (!is_bound()) {
854 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND,
855 "Encoding an unbound float value.");
856 return -1;
857 }
858
859 double value = (double)float_value;
860 if ((double)INFINITY == value) {
861 return p_tok.put_next_token(JSON_TOKEN_STRING, POS_INF_STR);
862 }
863 if (-(double)INFINITY == value) {
864 return p_tok.put_next_token(JSON_TOKEN_STRING, NEG_INF_STR);
865 }
866 if (isnan(value)) {
867 return p_tok.put_next_token(JSON_TOKEN_STRING, NAN_STR);
868 }
869
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);
874
875 char* tmp_str = mprintf(decimal_repr ? "%f" : "%e", value);
876 int enc_len = p_tok.put_next_token(JSON_TOKEN_NUMBER, tmp_str);
877 Free(tmp_str);
878 return enc_len;
879 }
880
881 int FLOAT::JSON_decode(const TTCN_Typedescriptor_t& p_td, JSON_Tokenizer& p_tok, boolean p_silent)
882 {
883 bound_flag = false;
884 json_token_t token = JSON_TOKEN_NONE;
885 char* value = 0;
886 size_t value_len = 0;
887 int dec_len = 0;
888 boolean use_default = p_td.json->default_value && 0 == p_tok.get_buffer_length();
889 if (use_default) {
890 // No JSON data in the buffer -> use default value
891 value = (char*)p_td.json->default_value;
892 value_len = strlen(value);
893 } else {
894 dec_len = p_tok.get_next_token(&token, &value, &value_len);
895 }
896 if (JSON_TOKEN_ERROR == token) {
897 JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_BAD_TOKEN_ERROR, "");
898 return JSON_ERROR_FATAL;
899 }
900 else if (JSON_TOKEN_STRING == token || use_default) {
901 if (0 == strncmp(value, POS_INF_STR + (use_default ? 1 : 0), value_len)) {
902 bound_flag = true;
903 float_value = INFINITY;
904 }
905 else if (0 == strncmp(value, NEG_INF_STR + (use_default ? 1 : 0), value_len)) {
906 bound_flag = true;
907 float_value = -INFINITY;
908 }
909 else if (0 == strncmp(value, NAN_STR + (use_default ? 1 : 0), value_len)) {
910 bound_flag = true;
911 #ifdef NAN
912 float_value = NAN;
913 #else
914 float_value = INFINITY + (-INFINITY);
915 #endif
916 }
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);
920 Free(spec_val);
921 bound_flag = false;
922 return JSON_ERROR_FATAL;
923 }
924 }
925 else if (JSON_TOKEN_NUMBER == token) {
926 char* value2 = mcopystrn(value, value_len);
927 sscanf(value2, "%lf", &float_value);
928 bound_flag = true;
929 Free(value2);
930 } else {
931 return JSON_ERROR_INVALID_TOKEN;
932 }
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);
938 bound_flag = true;
939 Free(value2);
940 }
941 return dec_len;
942 }
943
944
945 // global functions
946
947 double operator+(double double_value, const FLOAT& other_value)
948 {
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;
953 }
954
955 double operator-(double double_value, const FLOAT& other_value)
956 {
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;
961 }
962
963 double operator*(double double_value, const FLOAT& other_value)
964 {
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;
969 }
970
971 double operator/(double double_value, const FLOAT& other_value)
972 {
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;
978 }
979
980 boolean operator==(double double_value, const FLOAT& other_value)
981 {
982 other_value.must_bound("Unbound right operand of float comparison.");
983 return double_value == other_value.float_value;
984 }
985
986 boolean operator<(double double_value, const FLOAT& other_value)
987 {
988 other_value.must_bound("Unbound right operand of float comparison.");
989 return double_value < other_value.float_value;
990 }
991
992 boolean operator>(double double_value, const FLOAT& other_value)
993 {
994 other_value.must_bound("Unbound right operand of float comparison.");
995 return double_value > other_value.float_value;
996 }
997
998 // float template class
999
1000 void FLOAT_template::clean_up()
1001 {
1002 if (template_selection == VALUE_LIST ||
1003 template_selection == COMPLEMENTED_LIST)
1004 delete [] value_list.list_value;
1005 template_selection = UNINITIALIZED_TEMPLATE;
1006 }
1007
1008 void FLOAT_template::copy_template(const FLOAT_template& other_value)
1009 {
1010 switch (other_value.template_selection) {
1011 case SPECIFIC_VALUE:
1012 single_value = other_value.single_value;
1013 break;
1014 case OMIT_VALUE:
1015 case ANY_VALUE:
1016 case ANY_OR_OMIT:
1017 break;
1018 case VALUE_LIST:
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]);
1025 break;
1026 case VALUE_RANGE:
1027 value_range = other_value.value_range;
1028 break;
1029 default:
1030 TTCN_error("Copying an uninitialized/unsupported float template.");
1031 }
1032 set_selection(other_value);
1033 }
1034
1035 FLOAT_template::FLOAT_template()
1036 {
1037
1038 }
1039
1040 FLOAT_template::FLOAT_template(template_sel other_value)
1041 : Base_Template(other_value)
1042 {
1043 check_single_selection(other_value);
1044 }
1045
1046 FLOAT_template::FLOAT_template(double other_value)
1047 : Base_Template(SPECIFIC_VALUE)
1048 {
1049 single_value = other_value;
1050 }
1051
1052 FLOAT_template::FLOAT_template(const FLOAT& other_value)
1053 : Base_Template(SPECIFIC_VALUE)
1054 {
1055 other_value.must_bound("Creating a template from an unbound float value.");
1056 single_value = other_value.float_value;
1057 }
1058
1059 FLOAT_template::FLOAT_template(const OPTIONAL<FLOAT>& other_value)
1060 {
1061 switch (other_value.get_selection()) {
1062 case OPTIONAL_PRESENT:
1063 set_selection(SPECIFIC_VALUE);
1064 single_value = (double)(const FLOAT&)other_value;
1065 break;
1066 case OPTIONAL_OMIT:
1067 set_selection(OMIT_VALUE);
1068 break;
1069 default:
1070 TTCN_error("Creating a float template from an unbound optional field.");
1071 }
1072 }
1073
1074 FLOAT_template::FLOAT_template(const FLOAT_template& other_value)
1075 : Base_Template()
1076 {
1077 copy_template(other_value);
1078 }
1079
1080 FLOAT_template::~FLOAT_template()
1081 {
1082 clean_up();
1083 }
1084
1085 FLOAT_template& FLOAT_template::operator=(template_sel other_value)
1086 {
1087 check_single_selection(other_value);
1088 clean_up();
1089 set_selection(other_value);
1090 return *this;
1091 }
1092
1093 FLOAT_template& FLOAT_template::operator=(double other_value)
1094 {
1095 clean_up();
1096 set_selection(SPECIFIC_VALUE);
1097 single_value = other_value;
1098 return *this;
1099 }
1100
1101 FLOAT_template& FLOAT_template::operator=(const FLOAT& other_value)
1102 {
1103 other_value.must_bound("Assignment of an unbound float value "
1104 "to a template.");
1105 clean_up();
1106 set_selection(SPECIFIC_VALUE);
1107 single_value = other_value.float_value;
1108 return *this;
1109 }
1110
1111 FLOAT_template& FLOAT_template::operator=(const OPTIONAL<FLOAT>& other_value)
1112 {
1113 clean_up();
1114 switch (other_value.get_selection()) {
1115 case OPTIONAL_PRESENT:
1116 set_selection(SPECIFIC_VALUE);
1117 single_value = (double)(const FLOAT&)other_value;
1118 break;
1119 case OPTIONAL_OMIT:
1120 set_selection(OMIT_VALUE);
1121 break;
1122 default:
1123 TTCN_error("Assignment of an unbound optional field to a float template.");
1124 }
1125 return *this;
1126 }
1127
1128 FLOAT_template& FLOAT_template::operator=(const FLOAT_template& other_value)
1129 {
1130 if (&other_value != this) {
1131 clean_up();
1132 copy_template(other_value);
1133 }
1134 return *this;
1135 }
1136
1137 boolean FLOAT_template::match(double other_value) const
1138 {
1139 switch (template_selection) {
1140 case SPECIFIC_VALUE:
1141 return single_value == other_value;
1142 case OMIT_VALUE:
1143 return FALSE;
1144 case ANY_VALUE:
1145 case ANY_OR_OMIT:
1146 return TRUE;
1147 case VALUE_LIST:
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;
1153 case VALUE_RANGE:
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);
1158 default:
1159 TTCN_error("Matching with an uninitialized/unsupported float template.");
1160 }
1161 return FALSE;
1162 }
1163
1164 boolean FLOAT_template::match(const FLOAT& other_value) const
1165 {
1166 if (!other_value.is_bound()) return FALSE;
1167 return match(other_value.float_value);
1168 }
1169
1170
1171 void FLOAT_template::set_type(template_sel template_type,
1172 unsigned int list_length)
1173 {
1174 clean_up();
1175 switch (template_type) {
1176 case VALUE_LIST:
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];
1181 break;
1182 case VALUE_RANGE:
1183 set_selection(VALUE_RANGE);
1184 value_range.min_is_present = FALSE;
1185 value_range.max_is_present = FALSE;
1186 break;
1187 default:
1188 TTCN_error("Setting an invalid type for a float template.");
1189 }
1190 }
1191
1192 FLOAT_template& FLOAT_template::list_item(unsigned int list_index)
1193 {
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];
1200 }
1201
1202 void FLOAT_template::set_min(double min_value)
1203 {
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;
1211 }
1212
1213 void FLOAT_template::set_min(const FLOAT& min_value)
1214 {
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);
1218 }
1219
1220 void FLOAT_template::set_max(double max_value)
1221 {
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;
1229 }
1230
1231 void FLOAT_template::set_max(const FLOAT& max_value)
1232 {
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);
1236 }
1237
1238 double FLOAT_template::valueof() const
1239 {
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;
1244 }
1245
1246 void FLOAT_template::log() const
1247 {
1248 switch (template_selection) {
1249 case SPECIFIC_VALUE:
1250 log_float(single_value);
1251 break;
1252 case COMPLEMENTED_LIST:
1253 TTCN_Logger::log_event_str("complement ");
1254 // no break
1255 case VALUE_LIST:
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();
1260 }
1261 TTCN_Logger::log_char(')');
1262 break;
1263 case VALUE_RANGE:
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(')');
1271 break;
1272 default:
1273 log_generic();
1274 break;
1275 }
1276 log_ifpresent();
1277 }
1278
1279 void FLOAT_template::log_match(const FLOAT& match_value) const
1280 {
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(" := ");
1285 }
1286 match_value.log();
1287 TTCN_Logger::log_event_str(" with ");
1288 log();
1289 if (match(match_value)) TTCN_Logger::log_event_str(" matched");
1290 else TTCN_Logger::log_event_str(" unmatched");
1291 }
1292
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:
1297 *this = OMIT_VALUE;
1298 break;
1299 case Module_Param::MP_Any:
1300 *this = ANY_VALUE;
1301 break;
1302 case Module_Param::MP_AnyOrNone:
1303 *this = ANY_OR_OMIT;
1304 break;
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));
1310 }
1311 break;
1312 case Module_Param::MP_Float:
1313 *this = param.get_float();
1314 break;
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());
1319 break;
1320 default:
1321 param.type_error("float template");
1322 }
1323 is_ifpresent = param.get_ifpresent();
1324 }
1325
1326 void FLOAT_template::encode_text(Text_Buf& text_buf) const
1327 {
1328 encode_text_base(text_buf);
1329 switch (template_selection) {
1330 case OMIT_VALUE:
1331 case ANY_VALUE:
1332 case ANY_OR_OMIT:
1333 break;
1334 case SPECIFIC_VALUE:
1335 text_buf.push_double(single_value);
1336 break;
1337 case VALUE_LIST:
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);
1342 break;
1343 case VALUE_RANGE:
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);
1350 break;
1351 default:
1352 TTCN_error("Text encoder: Encoding an undefined/unsupported "
1353 "float template.");
1354 }
1355 }
1356
1357 void FLOAT_template::decode_text(Text_Buf& text_buf)
1358 {
1359 clean_up();
1360 decode_text_base(text_buf);
1361 switch (template_selection) {
1362 case OMIT_VALUE:
1363 case ANY_VALUE:
1364 case ANY_OR_OMIT:
1365 break;
1366 case SPECIFIC_VALUE:
1367 single_value = text_buf.pull_double();
1368 break;
1369 case VALUE_LIST:
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);
1375 break;
1376 case VALUE_RANGE:
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();
1383 break;
1384 default:
1385 TTCN_error("Text decoder: An unknown/unsupported selection was "
1386 "received for a float template.");
1387 }
1388 }
1389
1390 boolean FLOAT_template::is_present() const
1391 {
1392 if (template_selection==UNINITIALIZED_TEMPLATE) return FALSE;
1393 return !match_omit();
1394 }
1395
1396 boolean FLOAT_template::match_omit() const
1397 {
1398 if (is_ifpresent) return TRUE;
1399 switch (template_selection) {
1400 case OMIT_VALUE:
1401 case ANY_OR_OMIT:
1402 return TRUE;
1403 case VALUE_LIST:
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;
1409 default:
1410 return FALSE;
1411 }
1412 return FALSE;
1413 }
1414
1415 #ifndef TITAN_RUNTIME_2
1416 void FLOAT_template::check_restriction(template_res t_res, const char* t_name) const
1417 {
1418 if (template_selection==UNINITIALIZED_TEMPLATE) return;
1419 switch ((t_name&&(t_res==TR_VALUE))?TR_OMIT:t_res) {
1420 case TR_VALUE:
1421 if (!is_ifpresent && template_selection==SPECIFIC_VALUE) return;
1422 break;
1423 case TR_OMIT:
1424 if (!is_ifpresent && (template_selection==OMIT_VALUE ||
1425 template_selection==SPECIFIC_VALUE)) return;
1426 break;
1427 case TR_PRESENT:
1428 if (!match_omit()) return;
1429 break;
1430 default:
1431 return;
1432 }
1433 TTCN_error("Restriction `%s' on template of type %s violated.",
1434 get_res_name(t_res), t_name ? t_name : "float");
1435 }
1436 #endif
This page took 0.14545 seconds and 5 git commands to generate.