自主协议库编译通过
This commit is contained in:
572
mmslib/asn1/ard_flt.c
Normal file
572
mmslib/asn1/ard_flt.c
Normal file
@@ -0,0 +1,572 @@
|
||||
/************************************************************************/
|
||||
/* SISCO SOFTWARE MODULE HEADER *****************************************/
|
||||
/************************************************************************/
|
||||
/* (c) Copyright Systems Integration Specialists Company, Inc., */
|
||||
/* 1986 - 2001, All Rights Reserved. */
|
||||
/* */
|
||||
/* PROPRIETARY AND CONFIDENTIAL */
|
||||
/* */
|
||||
/* MODULE NAME : ard_float.c */
|
||||
/* PRODUCT(S) : ASN1DE */
|
||||
/* */
|
||||
/* MODULE DESCRIPTION : */
|
||||
/* */
|
||||
/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */
|
||||
/* */
|
||||
/* MODIFICATION LOG : */
|
||||
/* Date Who Rev Comments */
|
||||
/* -------- --- ------ ------------------------------------------- */
|
||||
/* 10/03/08 JRB 08 Make sure elmnt_len is legal. */
|
||||
/* 03/11/04 GLB 07 Remove "thisFileName" */
|
||||
/* 02/19/03 JRB 06 Use SD_BYTE_ORDER. */
|
||||
/* 02/19/03 JRB 05 Del VAX VMS support. For ALPHA VMS, assume */
|
||||
/* compiler option /FLOAT=IEEE_FLOAT is used */
|
||||
/* so it behaves like other systems. */
|
||||
/* 03/05/02 JRB 04 Eliminate warnings. */
|
||||
/* 12/20/01 JRB 03 Chg ASN1_CTXT to ASN1_DEC_CTXT. */
|
||||
/* 09/13/99 MDE 02 Added SD_CONST modifiers */
|
||||
/* 07/26/99 MDE 01 New module, derived from ad_float.c */
|
||||
/************************************************************************/
|
||||
|
||||
#include "glbtypes.h"
|
||||
#include "sysincs.h"
|
||||
#include "asn1r.h"
|
||||
#include "asn1log.h"
|
||||
|
||||
/************************************************************************/
|
||||
/* For debug version, use a static pointer to avoid duplication of */
|
||||
/* __FILE__ strings. */
|
||||
|
||||
#ifdef DEBUG_SISCO
|
||||
SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__;
|
||||
#endif
|
||||
|
||||
#ifdef ASN1_ARB_FLOAT
|
||||
static ST_INT16 _fp_common (ASN1_DEC_CTXT *ac, ST_INT16 *sign, ST_UINT16 *exp, ST_UCHAR *lptr,
|
||||
ST_INT16 *m, ST_UCHAR *next, ST_INT16 doubl_prec);
|
||||
#endif
|
||||
/************************************************************************/
|
||||
/************************************************************************/
|
||||
/* get_float */
|
||||
/* Function to convert the MMS floating point type in the ASN.1 message */
|
||||
/* stream to the single precision "float" type of the C programming */
|
||||
/* language. This function will handle any size mantissa (which is */
|
||||
/* rounded to fit into the local single precision floating point format)*/
|
||||
/* and any size exponent width up to 15 bits. Exponents too large or */
|
||||
/* small for the local representation translate into + or - infinity or */
|
||||
/* zero, as the case may be. The return codes are: */
|
||||
/* */
|
||||
/* 0 - finite valid floating pt # decoded successfully */
|
||||
/* 1 - invalid floating point number */
|
||||
/* 2 - exponent length greater than 15 */
|
||||
/* -1 - floating point value = NaN */
|
||||
/* -2 - floating point value = + infinity */
|
||||
/* -3 - floating point value = - infinity */
|
||||
/* */
|
||||
/************************************************************************/
|
||||
|
||||
ST_RET asn1r_get_float (ASN1_DEC_CTXT *ac, ST_FLOAT *out)
|
||||
{
|
||||
ST_UCHAR n; /* length of the exponent part */
|
||||
ST_UCHAR *ptr; /* char ptr to output float variable out*/
|
||||
ST_UCHAR *next; /* points to next data element */
|
||||
ST_UCHAR *original_asn1_field_ptr;
|
||||
ST_BOOLEAN float_is_zero;
|
||||
|
||||
#ifdef ASN1_ARB_FLOAT
|
||||
ST_UINT16 exp; /* local variable to hold exponent part */
|
||||
ST_INT i; /* utility variable */
|
||||
ST_INT16 sign; /* sign of the floating point quantity */
|
||||
ST_INT32 signexp; /* contains sign and exp parts of out */
|
||||
ST_INT16 m; /* # of fract bits in 1st 2 exp octets */
|
||||
ST_UINT32 *fract; /* contains fraction part of out */
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG_ASN1_DECODE
|
||||
if (!out)
|
||||
{
|
||||
slogCallStack (sLogCtrl,
|
||||
"get_float: attempt to reference through a NULL pointer");
|
||||
return(SD_FAILURE);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* MMS spec says FloatingPoint must be at least 2 octets */
|
||||
if (ac->asn1r_elmnt_len < 2)
|
||||
{
|
||||
ALOG_ERR0 ("ASN.1 decode: length < 2 not allowed for FloatingPoint");
|
||||
return (SD_FAILURE);
|
||||
}
|
||||
|
||||
next = ac->asn1r_field_ptr + ac->asn1r_elmnt_len;
|
||||
n = (ST_UCHAR) *(ac->asn1r_field_ptr++); /* read exponent width */
|
||||
|
||||
/* check to see if all the octets are 0 */
|
||||
|
||||
original_asn1_field_ptr = ac->asn1r_field_ptr;
|
||||
float_is_zero = SD_TRUE; /* assume the float = 0 */
|
||||
while(ac->asn1r_field_ptr < next)
|
||||
{
|
||||
if (*(ac->asn1r_field_ptr++) != 0)
|
||||
{
|
||||
float_is_zero = SD_FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (float_is_zero)
|
||||
{
|
||||
ac->asn1r_field_ptr = next;
|
||||
*out = (ST_FLOAT)0; /* this float = 0 */
|
||||
return(SD_SUCCESS); /* return success */
|
||||
}
|
||||
else
|
||||
ac->asn1r_field_ptr = original_asn1_field_ptr;
|
||||
|
||||
ptr = (ST_UCHAR *) out;
|
||||
|
||||
/* Treat case where MMS floating point format coincides with IEEE 754. */
|
||||
if (ac->asn1r_elmnt_len == 5 && n == 8)
|
||||
{
|
||||
#if SD_BYTE_ORDER==SD_BIG_ENDIAN /* big-endian (like Motorola) */
|
||||
*(ptr++) = (ST_UCHAR) *(ac->asn1r_field_ptr++);
|
||||
*(ptr++) = (ST_UCHAR) *(ac->asn1r_field_ptr++);
|
||||
*(ptr++) = (ST_UCHAR) *(ac->asn1r_field_ptr++);
|
||||
#else
|
||||
ac->asn1r_field_ptr += 3;
|
||||
*(ptr++) = (ST_UCHAR) *(ac->asn1r_field_ptr--);
|
||||
*(ptr++) = (ST_UCHAR) *(ac->asn1r_field_ptr--);
|
||||
*(ptr++) = (ST_UCHAR) *(ac->asn1r_field_ptr--);
|
||||
#endif
|
||||
*ptr = (ST_UCHAR) *ac->asn1r_field_ptr;
|
||||
|
||||
ac->asn1r_field_ptr = next;
|
||||
return (SD_SUCCESS);
|
||||
}
|
||||
|
||||
|
||||
#ifdef ASN1_ARB_FLOAT
|
||||
|
||||
/* Otherwise, convert arbitrary MMS floating point into local single- */
|
||||
/* precision floating point. */
|
||||
|
||||
/* Get exponent and sign information, and read in the fraction part of */
|
||||
/* the floating point number. */
|
||||
m = 15 - (ST_INT16)n;
|
||||
if ((i = _fp_common (ac,&sign,&exp,ptr,&m,next,SD_FALSE)) < 3)
|
||||
{
|
||||
*out = (ST_FLOAT)0;
|
||||
return ((ST_INT16) i);
|
||||
}
|
||||
|
||||
/* Shift fraction part to bottom 3 bytes, add 1, and then shift one */
|
||||
/* more byte. This rounds fraction to local precision and places it */
|
||||
/* nine bits into the floating point number, where it's supposed to go. */
|
||||
fract = (ST_UINT32 *) out;
|
||||
*fract = (*fract>>m) & (ST_UINT32)0x00FFFFFFL;
|
||||
*fract = (*fract + (ST_UINT32)0x00000001L) >> 1; /* add 1 and then shift */
|
||||
if (*fract & (ST_UINT32)0x00800000L)
|
||||
{ /* rounding may cause */
|
||||
exp++; /* exponent to increment*/
|
||||
*fract &= (ST_UINT32)0x007FFFFFL;
|
||||
}
|
||||
|
||||
/* OR the sign, exponent and fraction parts together to make a valid */
|
||||
/* local floating point value. */
|
||||
exp <<= 7; /* ready to be ORed with other parts */
|
||||
signexp = ((ST_INT32) exp) << 16;
|
||||
if (sign < 0)
|
||||
signexp |= 0x80000000L;
|
||||
*fract |= (ST_UINT32)signexp;
|
||||
|
||||
/* Return to calling routine with success indicated. */
|
||||
return (SD_SUCCESS);
|
||||
|
||||
#else /* No arbitrary float format support */
|
||||
return (SD_FAILURE);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/************************************************************************/
|
||||
/* get_double */
|
||||
/* Function to convert the MMS floating point type in the ASN.1 message */
|
||||
/* stream to the double precision "double" type of the C programming */
|
||||
/* language. This function will handle any size mantissa (which is */
|
||||
/* rounded to fit into the local double precision floating point format)*/
|
||||
/* and any size exponent width up to 15 bits. Exponents too large or */
|
||||
/* small for the local representation translate into + or - infinity or */
|
||||
/* zero, as the case may be. The return codes are: */
|
||||
/* */
|
||||
/* 0 - finite valid floating pt # decoded successfully */
|
||||
/* 1 - invalid floating point number */
|
||||
/* 2 - exponent length greater than 15 */
|
||||
/* -1 - floating point value = NaN */
|
||||
/* -2 - floating point value = + infinity */
|
||||
/* -3 - floating point value = - infinity */
|
||||
/* */
|
||||
/************************************************************************/
|
||||
|
||||
ST_RET asn1r_get_double (ASN1_DEC_CTXT *ac, ST_DOUBLE *out)
|
||||
{
|
||||
ST_UCHAR n; /* length of the exponent part */
|
||||
ST_UCHAR *ptr; /* char ptr to the out variable */
|
||||
ST_UCHAR *next; /* points to next data element */
|
||||
ST_UINT32 *h_ulong;
|
||||
ST_UINT32 *l_ulong;
|
||||
ST_UCHAR *original_asn1_field_ptr;
|
||||
ST_BOOLEAN float_is_zero;
|
||||
|
||||
#ifdef ASN1_ARB_FLOAT
|
||||
ST_INT garbage_bits_in_mantissa;
|
||||
ST_UCHAR round; /* flag indicating rounding, not trunc. */
|
||||
ST_UINT32 temp; /* utility variable */
|
||||
ST_UINT16 exp; /* value of exponent (biased) */
|
||||
ST_INT i; /* utility variable */
|
||||
ST_UINT32 signexp; /* contains sign and exp parts of out */
|
||||
ST_INT16 sign; /* sign of the floating point quantity */
|
||||
ST_INT16 m; /* # of fract bits in 1st fract octet */
|
||||
ST_INT16 local_double_exp_width; /* The local exp width of native double */
|
||||
ST_UINT32 *fract; /* points to fraction part of out */
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG_ASN1_DECODE
|
||||
if (!out)
|
||||
{
|
||||
slogCallStack (sLogCtrl,
|
||||
"get_double: attempt to reference through a NULL pointer");
|
||||
return(SD_FAILURE);
|
||||
}
|
||||
#endif
|
||||
|
||||
next = ac->asn1r_field_ptr + ac->asn1r_elmnt_len;
|
||||
n = (ST_UCHAR) *(ac->asn1r_field_ptr++); /* read exponent width */
|
||||
|
||||
/* check to see if all the octets are 0 */
|
||||
original_asn1_field_ptr = ac->asn1r_field_ptr;
|
||||
float_is_zero = SD_TRUE; /* assume the float = 0 */
|
||||
while(ac->asn1r_field_ptr < next)
|
||||
{
|
||||
if (*(ac->asn1r_field_ptr++) != 0)
|
||||
{
|
||||
float_is_zero = SD_FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (float_is_zero)
|
||||
{
|
||||
ac->asn1r_field_ptr = next;
|
||||
*out = (ST_FLOAT)0; /* this float = 0 */
|
||||
return(SD_SUCCESS); /* return success */
|
||||
}
|
||||
else
|
||||
ac->asn1r_field_ptr = original_asn1_field_ptr;
|
||||
|
||||
ptr = (ST_UCHAR *) out;
|
||||
h_ulong = (ST_UINT32 *) out;
|
||||
l_ulong = h_ulong + 1;
|
||||
|
||||
/* Treat case where MMS floating point format coincides with IEEE 754 */
|
||||
/* double precision floating point format. */
|
||||
if (ac->asn1r_elmnt_len == 9 && n == 11)
|
||||
{
|
||||
#if SD_BYTE_ORDER==SD_BIG_ENDIAN /* big-endian (like Motorola) */
|
||||
*(ptr++) = (ST_UCHAR) *(ac->asn1r_field_ptr++);
|
||||
*(ptr++) = (ST_UCHAR) *(ac->asn1r_field_ptr++);
|
||||
*(ptr++) = (ST_UCHAR) *(ac->asn1r_field_ptr++);
|
||||
*(ptr++) = (ST_UCHAR) *(ac->asn1r_field_ptr++);
|
||||
*(ptr++) = (ST_UCHAR) *(ac->asn1r_field_ptr++);
|
||||
*(ptr++) = (ST_UCHAR) *(ac->asn1r_field_ptr++);
|
||||
*(ptr++) = (ST_UCHAR) *(ac->asn1r_field_ptr++);
|
||||
#else
|
||||
ac->asn1r_field_ptr += 7;
|
||||
*(ptr++) = (ST_UCHAR) *(ac->asn1r_field_ptr--);
|
||||
*(ptr++) = (ST_UCHAR) *(ac->asn1r_field_ptr--);
|
||||
*(ptr++) = (ST_UCHAR) *(ac->asn1r_field_ptr--);
|
||||
*(ptr++) = (ST_UCHAR) *(ac->asn1r_field_ptr--);
|
||||
*(ptr++) = (ST_UCHAR) *(ac->asn1r_field_ptr--);
|
||||
*(ptr++) = (ST_UCHAR) *(ac->asn1r_field_ptr--);
|
||||
*(ptr++) = (ST_UCHAR) *(ac->asn1r_field_ptr--);
|
||||
#endif
|
||||
*ptr = (ST_UCHAR) *ac->asn1r_field_ptr;
|
||||
|
||||
ac->asn1r_field_ptr = next;
|
||||
return (SD_SUCCESS);
|
||||
}
|
||||
|
||||
#ifdef ASN1_ARB_FLOAT
|
||||
|
||||
/* Otherwise, convert arbitrary MMS floating point into local single- */
|
||||
/* precision floating point. */
|
||||
/* Get exponent and sign information, and read in the fraction part of */
|
||||
/* the floating point number. */
|
||||
m = 15 - (ST_INT16)n;
|
||||
if ((i = _fp_common (ac,&sign,&exp,ptr,&m,next,SD_TRUE)) < 3)
|
||||
{
|
||||
*out = (ST_DOUBLE)0;
|
||||
return ((ST_INT16) i);
|
||||
}
|
||||
|
||||
/* The number of bits used to store the exponent of a double precision */
|
||||
/* floating point number varies from machine to machine. The following */
|
||||
/* piece of code sets this local exponent width. */
|
||||
|
||||
/* Assume all systems now use IEEE 754 format */
|
||||
local_double_exp_width = 11;
|
||||
|
||||
/* The following piece of code calculates the number of bit positions */
|
||||
/* to shift the fraction bits in the mantissa. */
|
||||
/* (local_exp_width + sign width) - (non_mantisa_bits) */
|
||||
|
||||
garbage_bits_in_mantissa = 8 - m; /* num of garb bits in mantissa */
|
||||
i = (local_double_exp_width + 1) - garbage_bits_in_mantissa;
|
||||
/* was i = m + 4 */
|
||||
|
||||
fract = (ST_UINT32 *) out;
|
||||
|
||||
#if SD_BYTE_ORDER==SD_LITTLE_ENDIAN /* little-endian (like Intel) */
|
||||
fract++; /* high half of f.p. */
|
||||
#endif
|
||||
|
||||
/* save lowest i bits that will be lost when positioning the fraction */
|
||||
|
||||
temp =((0x00000001L << (local_double_exp_width + 1)) - 1L);
|
||||
temp = *fract & (temp >> garbage_bits_in_mantissa);
|
||||
|
||||
*fract <<= garbage_bits_in_mantissa; /* put fract at far left*/
|
||||
*fract >>= (local_double_exp_width + 1); /* shift fract in place */
|
||||
|
||||
/* grt rid of any sign and exponent */
|
||||
*fract &= 0x000fffff; /* other ports have 12 */
|
||||
|
||||
|
||||
/* pt at low half of fp */
|
||||
#if SD_BYTE_ORDER==SD_BIG_ENDIAN /* big-endian (like Motorola) */
|
||||
fract++;
|
||||
#else
|
||||
fract--;
|
||||
#endif
|
||||
|
||||
*fract >>= (i-1); /* low half of f.p. */
|
||||
if (*fract & (ST_UINT32)0x00000001L)
|
||||
round = SD_TRUE;
|
||||
else
|
||||
round = SD_FALSE;
|
||||
temp <<= (32-i);
|
||||
*fract = (*fract>>1) | temp; /* OR with bits from top half */
|
||||
|
||||
/* Round off the fraction part to fit into the local 8-byte double- */
|
||||
/* precision floating point number. */
|
||||
if (round)
|
||||
{ /* if low half is all 1's, then */
|
||||
if (*fract == 0xFFFFFFFF) /* rounding affects hi half too */
|
||||
{
|
||||
#if SD_BYTE_ORDER==SD_BIG_ENDIAN /* big-endian (like Motorola) */
|
||||
*(fract--) = 0;
|
||||
#else
|
||||
*(fract++) = 0;
|
||||
#endif
|
||||
*fract += 1;
|
||||
if (*fract & (ST_UINT32)0xFFF00000L) /* if adding one overflows into */
|
||||
{ /* exp part, increment exponent */
|
||||
exp += 1;
|
||||
*fract &= (ST_UINT32)0x000FFFFFL;
|
||||
}
|
||||
#if SD_BYTE_ORDER==SD_BIG_ENDIAN /* big-endian (like Motorola) */
|
||||
fract++; /* end up pointing to low half */
|
||||
#else
|
||||
fract--; /* end up pointing to low half */
|
||||
#endif
|
||||
}
|
||||
else
|
||||
*fract += 1;
|
||||
}
|
||||
|
||||
/* OR the sign, exponent and (high) fraction parts together to make a */
|
||||
/* valid local floating point value. */
|
||||
exp <<= 4; /* ready to be ORed with other parts */
|
||||
signexp = (ST_UINT32)exp << 16;
|
||||
if (sign < 0)
|
||||
signexp |= (ST_UINT32)0x80000000L;
|
||||
#if SD_BYTE_ORDER==SD_BIG_ENDIAN /* big-endian (like Motorola) */
|
||||
*(--fract) |= signexp;
|
||||
#else
|
||||
*(++fract) |= signexp;
|
||||
#endif
|
||||
|
||||
/* Return to calling routine with success indicated. */
|
||||
return (SD_SUCCESS);
|
||||
#else
|
||||
return (SD_FAILURE);
|
||||
#endif
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* _fp_common */
|
||||
/* Function to read the sign, exp, and fract parts of an MMS floating */
|
||||
/* point type into the designated arguments. This function represents */
|
||||
/* the common logic of the two functions: get_float and get_double. */
|
||||
/* Besides sign, exp, and fract, there are three other outputs from */
|
||||
/* this function: */
|
||||
/* asn1_field_ptr - global variable set to next data element in msg */
|
||||
/* m - modified in this function to be the number of fraction bits */
|
||||
/* in the 1st octet containing any fraction bits */
|
||||
/* return value - 0 - valid floating pt # with value of 0 */
|
||||
/* 1 - invalid floating point number */
|
||||
/* 2 - exponent length greater than 15 */
|
||||
/* 3 - valid, nonzero, finite floating pt # */
|
||||
/* -1 - floating point value = NaN */
|
||||
/* -2 - floating point value = + infinity */
|
||||
/* -3 - floating point value = - infinity */
|
||||
/************************************************************************/
|
||||
|
||||
#ifdef ASN1_ARB_FLOAT
|
||||
|
||||
static ST_INT16 _fp_common (
|
||||
ASN1_DEC_CTXT *ac, /* ASN1 context pointer */
|
||||
ST_INT16 *sign, /* sign */
|
||||
ST_UINT16 *exp, /* exponent translated to local repr'n */
|
||||
ST_UCHAR *lptr, /* pointer to local f.p. # */
|
||||
ST_INT16 *m, /* begins as # of fract bits in 1st two */
|
||||
/* octets, modified in this function */
|
||||
ST_UCHAR *next, /* pointer to next data element */
|
||||
ST_INT16 doubl_prec) /* local precision - single or double */
|
||||
{
|
||||
ST_INT16 lbias; /* bias of local floating point type */
|
||||
ST_UINT16 lmaxexp; /* max exponent of local f.p. type */
|
||||
ST_INT16 lfract; /* local precision length in bytes */
|
||||
ST_UINT16 bias; /* bias for MMS f.p. type being decoded */
|
||||
ST_UCHAR nonzero; /* flag indicating if fract part is !=0 */
|
||||
ST_INT i; /* utility variable */
|
||||
ST_UINT16 temp1; /* utility variable */
|
||||
ST_UCHAR temp2; /* utility variable */
|
||||
|
||||
/* Initialize variables dependent on the precision of the local f.p. */
|
||||
/* representation (either single or double). */
|
||||
if (doubl_prec)
|
||||
{
|
||||
lbias = 1023;
|
||||
lmaxexp = 2047;
|
||||
lfract = 7;
|
||||
}
|
||||
else
|
||||
{
|
||||
lbias = 127;
|
||||
lmaxexp = 255;
|
||||
lfract = 3;
|
||||
}
|
||||
|
||||
/* First, check size of exponent and fraction parts based on element */
|
||||
/* length and number of fraction bits in 1st two bytes. */
|
||||
if (ac->asn1r_elmnt_len < 3) /* must have minimum of */
|
||||
{ /* 2 bytes for f.p. # */
|
||||
ac->asn1r_field_ptr = next;
|
||||
return (SD_FAILURE);
|
||||
}
|
||||
if (*m < 0) /* exp part too big */
|
||||
{
|
||||
ac->asn1r_field_ptr = next;
|
||||
return (2);
|
||||
}
|
||||
if (*m >= 15) /* exp part too small */
|
||||
{
|
||||
ac->asn1r_field_ptr = next;
|
||||
return (SD_FAILURE);
|
||||
}
|
||||
|
||||
/* Move exponent and sign parts into *exp variable for manipulation. */
|
||||
temp1 = ((ST_UINT16) *(ac->asn1r_field_ptr++)) << 8;
|
||||
*exp = temp1 | ((ST_UINT16) *(ac->asn1r_field_ptr++) & (ST_UINT16)0x00ff);
|
||||
|
||||
/* Determine sign, and mask out. */
|
||||
if (*exp & (ST_UINT16)0x8000)
|
||||
{
|
||||
*sign = -1;
|
||||
*exp = *exp & (ST_UINT16)0x7FFF; /* zero sign bit */
|
||||
}
|
||||
else
|
||||
*sign = 1;
|
||||
|
||||
/* Reset asn1_field_ptr to point to 1st octet containing any fraction bits. */
|
||||
if (*m > 8)
|
||||
ac->asn1r_field_ptr -= 2;
|
||||
else if (*m > 0)
|
||||
ac->asn1r_field_ptr--;
|
||||
|
||||
/* Calculate bias of MMS floating point number before m is changed. */
|
||||
bias = (ST_UINT16)0x7FFF >> (*m+1); /* bias = 2**(n-1) - 1 */
|
||||
|
||||
/* Determine if exponent part is all 1's. In this case, MMS float = NaN */
|
||||
/* or infinity, so return with appropriate return code. */
|
||||
|
||||
*exp = *exp >> *m; /* get rid of fract bits on right */
|
||||
temp1 = (ST_UINT16)0x7FFF >> *m; /* prepare comparison bytes */
|
||||
*m = *m%8;
|
||||
if (*m == 0)
|
||||
*m = 8; /* m = # fract bits in current octet */
|
||||
if (*exp == temp1) /* check for all 1's in exponent */
|
||||
{
|
||||
nonzero = SD_FALSE; /* now check for all 0's in fraction */
|
||||
temp2 = (ST_UCHAR) (*(ac->asn1r_field_ptr++) & ~(0xFF<<*m));
|
||||
while (ac->asn1r_field_ptr <= next) /* if all fract bits = */
|
||||
{ /* 0, then we have a + */
|
||||
if (temp2) /* or - infinity */
|
||||
{
|
||||
nonzero = SD_TRUE;
|
||||
break;
|
||||
}
|
||||
temp2 = (ST_UCHAR) *(ac->asn1r_field_ptr++);
|
||||
}
|
||||
ac->asn1r_field_ptr = next;
|
||||
if (nonzero)
|
||||
return (-1); /* nonzero fract => NaN */
|
||||
else if (*sign > 0)
|
||||
return (-2); /* case of + infinity */
|
||||
else
|
||||
return (-3); /* case of - infinity */
|
||||
}
|
||||
|
||||
/* Now that we know MMS float is a valid finite value, translate its */
|
||||
/* exponent part into the exponent for the local representation. */
|
||||
if ((i = (ST_INT16)*exp + lbias - (ST_INT16)bias) < 0)
|
||||
return (SD_SUCCESS); /* Value too small to represent locally.*/
|
||||
|
||||
*exp = (ST_UINT16) i;
|
||||
if (*exp > lmaxexp) /* biased local exp */
|
||||
{ /* value too big to */
|
||||
ac->asn1r_field_ptr = next; /* represent locally - */
|
||||
if (*sign > 0) /* treat as + or - inf */
|
||||
return (-2);
|
||||
else
|
||||
return (-3);
|
||||
}
|
||||
|
||||
/* Move fraction part into local variable. */
|
||||
#if SD_BYTE_ORDER==SD_BIG_ENDIAN /* big-endian (like Motorola) */
|
||||
for (i=0;i<lfract;i++)
|
||||
{
|
||||
if (ac->asn1r_field_ptr < next)
|
||||
*(lptr++) = (ST_UCHAR) *(ac->asn1r_field_ptr++);
|
||||
else
|
||||
{
|
||||
*(lptr++) = (ST_UCHAR) 0; /* zero fill if local precision */
|
||||
}
|
||||
}
|
||||
#else
|
||||
ac->asn1r_field_ptr += lfract;
|
||||
for (i=0;i<lfract;i++)
|
||||
{
|
||||
if (ac->asn1r_field_ptr < next)
|
||||
*(lptr++) = (ST_UCHAR) *(ac->asn1r_field_ptr--);
|
||||
else
|
||||
{
|
||||
*(lptr++) = (ST_UCHAR) 0; /* zero fill if local precision */
|
||||
ac->asn1r_field_ptr--; /* is greater than MMS f.p. */
|
||||
}
|
||||
}
|
||||
*lptr = (ST_UCHAR) *ac->asn1r_field_ptr; /* we know last byte < next */
|
||||
#endif
|
||||
|
||||
ac->asn1r_field_ptr = next;
|
||||
return (3); /* normal case */
|
||||
}
|
||||
#endif /* end of ARB FLOAT support */
|
||||
Reference in New Issue
Block a user