Added support for storing 64 bit numbers
git-svn-id: https://svn.code.sf.net/p/flaim/code/trunk@805 0109f412-320b-0410-ab79-c3e0c5ffbbe6
This commit is contained in:
@@ -24,36 +24,6 @@
|
||||
|
||||
#include "flaimsys.h"
|
||||
|
||||
// Static Data
|
||||
|
||||
FLMBYTE ucMaxBcdINT32[] =
|
||||
{
|
||||
0x21,
|
||||
0x47,
|
||||
0x48,
|
||||
0x36,
|
||||
0x47
|
||||
};
|
||||
|
||||
FLMBYTE ucMinBcdINT32[] =
|
||||
{
|
||||
0xB2,
|
||||
0x14,
|
||||
0x74,
|
||||
0x83,
|
||||
0x64,
|
||||
0x8F
|
||||
};
|
||||
|
||||
FLMBYTE ucMaxBcdUINT32[] =
|
||||
{
|
||||
0x42,
|
||||
0x94,
|
||||
0x96,
|
||||
0x72,
|
||||
0x95
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
Desc: Given an unsigned number create the matching FLAIM-specific BCD
|
||||
number.
|
||||
@@ -81,7 +51,7 @@ FLMEXP RCODE FLMAPI FlmUINT2Storage(
|
||||
*pucNibStk++ = 0x0F;
|
||||
|
||||
// push digits
|
||||
// do 32 bit division until we get down to 16 bits
|
||||
// do 32 bit division until we get down to last digit
|
||||
|
||||
while( uiNum >= 10)
|
||||
{
|
||||
@@ -110,6 +80,62 @@ FLMEXP RCODE FLMAPI FlmUINT2Storage(
|
||||
return( FERR_OK);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
Desc: Given a 64 bit unsigned number create the matching FLAIM-specific BCD
|
||||
number.
|
||||
Note: If terminating byte is half-full, low-nibble value is
|
||||
undefined. Example: -125 creates B1-25-FX
|
||||
Method: Using a MOD algorithm, stack BCD values -- popping to
|
||||
destination reverses the order for correct final sequence
|
||||
****************************************************************************/
|
||||
FLMEXP RCODE FLMAPI FlmUINT64ToStorage(
|
||||
FLMUINT64 ui64Num,
|
||||
FLMUINT * puiBufLength,
|
||||
FLMBYTE * pBuf)
|
||||
{
|
||||
FLMBYTE ucNibStk[ F_MAX_NUM64_BUF + 1];
|
||||
FLMBYTE * pucNibStk;
|
||||
|
||||
flmAssert( *puiBufLength >= F_MAX_NUM64_BUF);
|
||||
|
||||
// push spare (undefined) nibble for possible half-used terminating byte
|
||||
|
||||
pucNibStk = &ucNibStk[ 1];
|
||||
|
||||
// push terminator nibble -- popped last
|
||||
|
||||
*pucNibStk++ = 0x0F;
|
||||
|
||||
// push digits
|
||||
// do 64 bit division until we get down to last digit.
|
||||
|
||||
while( ui64Num >= 10)
|
||||
{
|
||||
// push BCD nibbles in reverse order
|
||||
|
||||
*pucNibStk++ = (FLMBYTE)(ui64Num % 10);
|
||||
ui64Num /= 10;
|
||||
}
|
||||
|
||||
// push last nibble of number
|
||||
|
||||
*pucNibStk++ = (FLMBYTE)ui64Num;
|
||||
|
||||
// count: nibbleCount / 2 and truncate
|
||||
|
||||
*puiBufLength = ((pucNibStk - ucNibStk) >> 1);
|
||||
|
||||
// Pop stack and pack nibbles into byte stream a pair at a time
|
||||
|
||||
do
|
||||
{
|
||||
*pBuf++ = (FLMBYTE)((pucNibStk[ -1] << 4) | pucNibStk[ -2]);
|
||||
}
|
||||
while( (pucNibStk -= 2) > &ucNibStk[ 1]);
|
||||
|
||||
return( FERR_OK);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
Desc: Given an signed number create the matching FLAIM-specific BCD
|
||||
number.
|
||||
@@ -117,7 +143,6 @@ Note: If terminating byte is half-full, low-nibble value is
|
||||
undefined. Example: -125 creates B1-25-FX
|
||||
Method: Using a MOD algorithm, stack BCD values -- popping to
|
||||
destination reverses the order for correct final sequence
|
||||
WARNING: -2,147,483,648 may yield different results on different platforms
|
||||
****************************************************************************/
|
||||
FLMEXP RCODE FLMAPI FlmINT2Storage(
|
||||
FLMINT iNum,
|
||||
@@ -127,16 +152,30 @@ FLMEXP RCODE FLMAPI FlmINT2Storage(
|
||||
FLMUINT uiNum;
|
||||
FLMBYTE ucNibStk[ F_MAX_NUM_BUF + 1];
|
||||
FLMBYTE * pucNibStk;
|
||||
FLMINT iNegFlag;
|
||||
FLMBOOL bNegFlag;
|
||||
|
||||
flmAssert( *puiBufLength >= F_MAX_NUM_BUF);
|
||||
|
||||
pucNibStk = &ucNibStk[ 1];
|
||||
*pucNibStk++ = 0x0F;
|
||||
|
||||
uiNum = ((iNegFlag = iNum < 0) != 0)
|
||||
? -iNum
|
||||
: iNum;
|
||||
if (iNum < 0)
|
||||
{
|
||||
bNegFlag = TRUE;
|
||||
if (iNum == FLM_MIN_INT)
|
||||
{
|
||||
uiNum = (FLMUINT)(FLM_MAX_INT) + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
uiNum = (FLMUINT)(-iNum);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
bNegFlag = FALSE;
|
||||
uiNum = (FLMUINT)iNum;
|
||||
}
|
||||
|
||||
while( uiNum >= 10)
|
||||
{
|
||||
@@ -146,7 +185,72 @@ FLMEXP RCODE FLMAPI FlmINT2Storage(
|
||||
|
||||
*pucNibStk++ = (FLMBYTE)uiNum;
|
||||
|
||||
if( iNegFlag)
|
||||
if( bNegFlag)
|
||||
{
|
||||
*pucNibStk++ = 0x0B;
|
||||
}
|
||||
|
||||
*puiBufLength = ((pucNibStk - ucNibStk) >> 1);
|
||||
|
||||
do
|
||||
{
|
||||
*pBuf++ = (FLMBYTE)((pucNibStk[ -1] << 4) | pucNibStk[ -2]);
|
||||
}
|
||||
while( (pucNibStk -= 2) > &ucNibStk[ 1]);
|
||||
|
||||
return( FERR_OK);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
Desc: Given a 64 bit signed number create the matching FLAIM-specific BCD
|
||||
number.
|
||||
Note: If terminating byte is half-full, low-nibble value is
|
||||
undefined. Example: -125 creates B1-25-FX
|
||||
Method: Using a MOD algorithm, stack BCD values -- popping to
|
||||
destination reverses the order for correct final sequence
|
||||
****************************************************************************/
|
||||
FLMEXP RCODE FLMAPI FlmINT64ToStorage(
|
||||
FLMINT64 i64Num,
|
||||
FLMUINT * puiBufLength,
|
||||
FLMBYTE * pBuf)
|
||||
{
|
||||
FLMUINT64 ui64Num;
|
||||
FLMBYTE ucNibStk[ F_MAX_NUM64_BUF + 1];
|
||||
FLMBYTE * pucNibStk;
|
||||
FLMBOOL bNegFlag;
|
||||
|
||||
flmAssert( *puiBufLength >= F_MAX_NUM64_BUF);
|
||||
|
||||
pucNibStk = &ucNibStk[ 1];
|
||||
*pucNibStk++ = 0x0F;
|
||||
|
||||
if (i64Num < 0)
|
||||
{
|
||||
bNegFlag = TRUE;
|
||||
if (i64Num == FLM_MIN_INT64)
|
||||
{
|
||||
ui64Num = (FLMUINT64)(FLM_MAX_INT64) + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
ui64Num = (FLMUINT64)(-i64Num);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
bNegFlag = FALSE;
|
||||
ui64Num = (FLMUINT64)i64Num;
|
||||
}
|
||||
|
||||
while( ui64Num >= 10)
|
||||
{
|
||||
*pucNibStk++ = (FLMBYTE)(ui64Num % 10);
|
||||
ui64Num /= 10;
|
||||
}
|
||||
|
||||
*pucNibStk++ = (FLMBYTE)ui64Num;
|
||||
|
||||
if (bNegFlag)
|
||||
{
|
||||
*pucNibStk++ = 0x0B;
|
||||
}
|
||||
@@ -172,28 +276,136 @@ FLMEXP RCODE FLMAPI FlmStorage2INT(
|
||||
const FLMBYTE * pucValue,
|
||||
FLMINT * piNum)
|
||||
{
|
||||
RCODE rc = FERR_OK;
|
||||
BCD_TYPE bcd;
|
||||
RCODE rc = FERR_OK;
|
||||
FLMUINT uiNum;
|
||||
FLMBOOL bNegFlag;
|
||||
|
||||
if( RC_OK(rc = flmBcd2Num( uiValueType, uiValueLength, pucValue, &bcd)))
|
||||
if( RC_OK(rc = flmBcd2Num( uiValueType, uiValueLength, pucValue,
|
||||
&uiNum, &bNegFlag)))
|
||||
{
|
||||
if( bcd.bNegFlag)
|
||||
if (bNegFlag)
|
||||
{
|
||||
*piNum = -((FLMINT)bcd.uiNum);
|
||||
return( (bcd.uiNibCnt < 11) ||
|
||||
(bcd.uiNibCnt == 11 &&
|
||||
(!bcd.pucPtr || (f_memcmp( bcd.pucPtr, ucMinBcdINT32, 6) <= 0)))
|
||||
? FERR_OK
|
||||
: RC_SET( FERR_CONV_NUM_UNDERFLOW));
|
||||
|
||||
// If bNegFlag is set, we will have already checked to make sure
|
||||
// the value is in range inside of flmBcd2Num.
|
||||
|
||||
if (uiNum == (FLMUINT)(FLM_MAX_INT) + 1)
|
||||
{
|
||||
*piNum = FLM_MIN_INT;
|
||||
}
|
||||
else
|
||||
{
|
||||
*piNum = -((FLMINT)uiNum);
|
||||
}
|
||||
}
|
||||
|
||||
// If the value is positive, we will have checked to make sure the
|
||||
// number did not overflow FLM_MAX_UINT, but not FLM_MAX_INT.
|
||||
|
||||
else if (uiNum > (FLMUINT)(FLM_MAX_INT))
|
||||
{
|
||||
rc = RC_SET( FERR_CONV_NUM_OVERFLOW);
|
||||
}
|
||||
else
|
||||
{
|
||||
*piNum = (FLMINT)bcd.uiNum;
|
||||
return( (bcd.uiNibCnt < 10) ||
|
||||
(bcd.uiNibCnt == 10 &&
|
||||
(!bcd.pucPtr || (f_memcmp( bcd.pucPtr, ucMaxBcdINT32, 5) <= 0)))
|
||||
? FERR_OK
|
||||
: RC_SET( FERR_CONV_NUM_OVERFLOW));
|
||||
*piNum = (FLMINT)uiNum;
|
||||
}
|
||||
}
|
||||
|
||||
return( rc);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
Desc: Returns a signed value from a BCD value.
|
||||
The data may be a number type, or context type.
|
||||
****************************************************************************/
|
||||
FLMEXP RCODE FLMAPI FlmStorage2INT32(
|
||||
FLMUINT uiValueType,
|
||||
FLMUINT uiValueLength,
|
||||
const FLMBYTE * pucValue,
|
||||
FLMINT32 * pi32Num)
|
||||
{
|
||||
RCODE rc = FERR_OK;
|
||||
FLMUINT uiNum;
|
||||
FLMBOOL bNegFlag;
|
||||
|
||||
if( RC_OK(rc = flmBcd2Num( uiValueType, uiValueLength, pucValue,
|
||||
&uiNum, &bNegFlag)))
|
||||
{
|
||||
if (bNegFlag)
|
||||
{
|
||||
if (uiNum > (FLMUINT)(FLM_MAX_INT32) + 1)
|
||||
{
|
||||
rc = RC_SET( FERR_CONV_NUM_UNDERFLOW);
|
||||
}
|
||||
else if (uiNum == (FLMUINT)(FLM_MAX_INT32) + 1)
|
||||
{
|
||||
*pi32Num = FLM_MIN_INT32;
|
||||
}
|
||||
else
|
||||
{
|
||||
*pi32Num = -((FLMINT32)uiNum);
|
||||
}
|
||||
}
|
||||
|
||||
// If the value is positive, we will have checked to make sure the
|
||||
// number did not overflow FLM_MAX_UINT, but not FLM_MAX_INT32.
|
||||
|
||||
else if (uiNum > (FLMUINT)(FLM_MAX_INT32))
|
||||
{
|
||||
rc = RC_SET( FERR_CONV_NUM_OVERFLOW);
|
||||
}
|
||||
else
|
||||
{
|
||||
*pi32Num = (FLMINT32)uiNum;
|
||||
}
|
||||
}
|
||||
|
||||
return( rc);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
Desc: Returns a 64 bit signed value from a BCD value.
|
||||
The data may be a number type, or context type.
|
||||
****************************************************************************/
|
||||
FLMEXP RCODE FLMAPI FlmStorage2INT64(
|
||||
FLMUINT uiValueType,
|
||||
FLMUINT uiValueLength,
|
||||
const FLMBYTE * pucValue,
|
||||
FLMINT64 * pi64Num)
|
||||
{
|
||||
RCODE rc = FERR_OK;
|
||||
FLMUINT64 ui64Num;
|
||||
FLMBOOL bNegFlag;
|
||||
|
||||
if( RC_OK(rc = flmBcd2Num64( uiValueType, uiValueLength, pucValue,
|
||||
&ui64Num, &bNegFlag)))
|
||||
{
|
||||
if (bNegFlag)
|
||||
{
|
||||
// If bNegFlag is set, we will have already checked to make sure
|
||||
// the value is in range inside of flmBcd2Num64.
|
||||
|
||||
if (ui64Num == (FLMUINT64)(FLM_MAX_INT64) + 1)
|
||||
{
|
||||
*pi64Num = FLM_MIN_INT64;
|
||||
}
|
||||
else
|
||||
{
|
||||
*pi64Num = -((FLMINT64)ui64Num);
|
||||
}
|
||||
}
|
||||
|
||||
// If the value is positive, we will have checked to make sure the
|
||||
// number did not overflow FLM_MAX_UINT64, but not FLM_MAX_INT64.
|
||||
|
||||
else if (ui64Num > (FLMUINT64)(FLM_MAX_INT64))
|
||||
{
|
||||
rc = RC_SET( FERR_CONV_NUM_OVERFLOW);
|
||||
}
|
||||
else
|
||||
{
|
||||
*pi64Num = (FLMINT64)ui64Num;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -210,31 +422,16 @@ FLMEXP RCODE FLMAPI FlmStorage2UINT(
|
||||
const FLMBYTE * pucValue,
|
||||
FLMUINT * puiNum)
|
||||
{
|
||||
RCODE rc = FERR_OK;
|
||||
BCD_TYPE bcd;
|
||||
RCODE rc = FERR_OK;
|
||||
FLMBOOL bNegFlag;
|
||||
|
||||
if( RC_OK( rc = flmBcd2Num( uiValueType, uiValueLength, pucValue, &bcd)))
|
||||
if( RC_OK( rc = flmBcd2Num( uiValueType, uiValueLength, pucValue,
|
||||
puiNum, &bNegFlag)))
|
||||
{
|
||||
*puiNum = bcd.uiNum;
|
||||
|
||||
if( bcd.bNegFlag)
|
||||
if (bNegFlag)
|
||||
{
|
||||
rc = RC_SET( FERR_CONV_NUM_UNDERFLOW);
|
||||
}
|
||||
else if( bcd.uiNibCnt < 10)
|
||||
{
|
||||
rc = FERR_OK;
|
||||
}
|
||||
else if( bcd.uiNibCnt == 10)
|
||||
{
|
||||
rc = (!bcd.pucPtr || (f_memcmp( bcd.pucPtr, ucMaxBcdUINT32, 5) <= 0))
|
||||
? FERR_OK
|
||||
: RC_SET( FERR_CONV_NUM_OVERFLOW);
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = RC_SET( FERR_CONV_NUM_OVERFLOW);
|
||||
}
|
||||
}
|
||||
|
||||
return( rc);
|
||||
@@ -250,31 +447,60 @@ FLMEXP RCODE FLMAPI FlmStorage2UINT32(
|
||||
const FLMBYTE * pucValue,
|
||||
FLMUINT32 * pui32Num)
|
||||
{
|
||||
RCODE rc = FERR_OK;
|
||||
BCD_TYPE bcd;
|
||||
RCODE rc = FERR_OK;
|
||||
FLMUINT uiNum;
|
||||
FLMBOOL bNegFlag;
|
||||
|
||||
if( RC_OK(rc = flmBcd2Num( uiValueType, uiValueLength, pucValue, &bcd)))
|
||||
if( RC_OK(rc = flmBcd2Num( uiValueType, uiValueLength, pucValue,
|
||||
&uiNum, &bNegFlag)))
|
||||
{
|
||||
*pui32Num = (FLMUINT32)bcd.uiNum;
|
||||
|
||||
if( bcd.bNegFlag)
|
||||
if (bNegFlag)
|
||||
{
|
||||
rc = RC_SET( FERR_CONV_NUM_UNDERFLOW);
|
||||
}
|
||||
else if( bcd.uiNibCnt < 10)
|
||||
{
|
||||
rc = FERR_OK;
|
||||
}
|
||||
else if( bcd.uiNibCnt == 10)
|
||||
{
|
||||
rc = (!bcd.pucPtr || (f_memcmp( bcd.pucPtr, ucMaxBcdUINT32, 5) <= 0))
|
||||
? FERR_OK
|
||||
: RC_SET( FERR_CONV_NUM_OVERFLOW);
|
||||
}
|
||||
else
|
||||
|
||||
// On 64 bit platforms FLM_MAX_UINT32 will be less than FLM_MAX_UINT
|
||||
// so we need to test against it. Otherwise, we have already tested
|
||||
// against FLM_MAX_UINT, and it is the same as FLM_MAX_UINT32, so there
|
||||
// is no need to test against it.
|
||||
|
||||
#ifdef FLM_64BIT
|
||||
else if (uiNum > FLM_MAX_UINT32)
|
||||
{
|
||||
rc = RC_SET( FERR_CONV_NUM_OVERFLOW);
|
||||
}
|
||||
#endif
|
||||
|
||||
else
|
||||
{
|
||||
*pui32Num = (FLMUINT32)uiNum;
|
||||
}
|
||||
}
|
||||
|
||||
return( rc);
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
Desc: Returns a unsigned value from a BCD value.
|
||||
The data may be a number type, or context type.
|
||||
****************************************************************************/
|
||||
FLMEXP RCODE FLMAPI FlmStorage2UINT64(
|
||||
FLMUINT uiValueType,
|
||||
FLMUINT uiValueLength,
|
||||
const FLMBYTE * pucValue,
|
||||
FLMUINT64 * pui64Num)
|
||||
{
|
||||
RCODE rc = FERR_OK;
|
||||
FLMBOOL bNegFlag;
|
||||
|
||||
if( RC_OK(rc = flmBcd2Num64( uiValueType, uiValueLength, pucValue,
|
||||
pui64Num, &bNegFlag)))
|
||||
{
|
||||
if (bNegFlag)
|
||||
{
|
||||
rc = RC_SET( FERR_CONV_NUM_UNDERFLOW);
|
||||
}
|
||||
}
|
||||
|
||||
return( rc);
|
||||
@@ -288,89 +514,159 @@ RCODE flmBcd2Num(
|
||||
FLMUINT uiValueType,
|
||||
FLMUINT uiValueLength,
|
||||
const FLMBYTE * pucValue,
|
||||
BCD_TYPE * bcd)
|
||||
FLMUINT * puiNum,
|
||||
FLMBOOL * pbNegFlag)
|
||||
{
|
||||
if( pucValue == NULL)
|
||||
RCODE rc = FERR_OK;
|
||||
FLMUINT uiTotalNum;
|
||||
FLMUINT uiByte;
|
||||
FLMUINT uiNibble;
|
||||
FLMUINT uiMaxBeforeMultValue;
|
||||
FLMUINT uiMaxValue;
|
||||
|
||||
if (pucValue == NULL)
|
||||
{
|
||||
return( RC_SET( FERR_CONV_NULL_SRC));
|
||||
rc = RC_SET( FERR_CONV_NULL_SRC);
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
switch( uiValueType)
|
||||
switch (uiValueType)
|
||||
{
|
||||
case FLM_NUMBER_TYPE:
|
||||
{
|
||||
FLMUINT uiTotalNum = 0;
|
||||
FLMUINT uiByte;
|
||||
FLMUINT uiNibCnt;
|
||||
|
||||
bcd->pucPtr = pucValue;
|
||||
uiTotalNum = 0;
|
||||
if ((*pucValue & 0xF0) == 0xB0)
|
||||
{
|
||||
*pbNegFlag = TRUE;
|
||||
uiNibble = 1;
|
||||
uiMaxBeforeMultValue = ((FLMUINT)(FLM_MAX_INT) + 1) / 10;
|
||||
uiMaxValue = ((FLMUINT)(FLM_MAX_INT) + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
*pbNegFlag = FALSE;
|
||||
uiNibble = 0;
|
||||
uiMaxBeforeMultValue = (FLM_MAX_UINT) / 10;
|
||||
uiMaxValue = FLM_MAX_UINT;
|
||||
}
|
||||
|
||||
// Get each nibble and use to create the number
|
||||
|
||||
for( bcd->bNegFlag = (FLMBOOL)(uiNibCnt = ((*pucValue & 0xF0) == 0xB0)
|
||||
? 1
|
||||
: 0);
|
||||
uiNibCnt <= FLM_MAX_NIB_CNT;
|
||||
uiNibCnt++ )
|
||||
while (uiValueLength)
|
||||
{
|
||||
|
||||
uiByte = (uiNibCnt & 0x01)
|
||||
? (FLMUINT)(0x0F & *pucValue++)
|
||||
: (FLMUINT)(*pucValue >> 4);
|
||||
|
||||
if( uiByte == 0x0F)
|
||||
|
||||
// An odd value for uiNibble means we are on the 2nd nibble of
|
||||
// the byte.
|
||||
|
||||
if (uiNibble & 1)
|
||||
{
|
||||
uiByte = (FLMINT)(*pucValue & 0x0F);
|
||||
pucValue++;
|
||||
uiValueLength--;
|
||||
}
|
||||
else
|
||||
{
|
||||
uiByte = (FLMUINT)(*pucValue >> 4);
|
||||
}
|
||||
uiNibble++;
|
||||
if (uiByte == 0x0F)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
uiTotalNum = (uiTotalNum << 3) + (uiTotalNum << 1) + uiByte;
|
||||
if (uiTotalNum > uiMaxBeforeMultValue)
|
||||
{
|
||||
if (*pbNegFlag)
|
||||
{
|
||||
rc = RC_SET( FERR_CONV_NUM_UNDERFLOW);
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = RC_SET( FERR_CONV_NUM_OVERFLOW);
|
||||
}
|
||||
goto Exit;
|
||||
}
|
||||
uiTotalNum = (uiTotalNum << 3) + (uiTotalNum << 1);
|
||||
if (uiTotalNum > uiMaxValue - uiByte)
|
||||
{
|
||||
if (*pbNegFlag)
|
||||
{
|
||||
rc = RC_SET( FERR_CONV_NUM_UNDERFLOW);
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = RC_SET( FERR_CONV_NUM_OVERFLOW);
|
||||
}
|
||||
goto Exit;
|
||||
}
|
||||
uiTotalNum += uiByte;
|
||||
}
|
||||
|
||||
bcd->uiNibCnt = uiNibCnt;
|
||||
bcd->uiNum = uiTotalNum;
|
||||
*puiNum = uiTotalNum;
|
||||
break;
|
||||
}
|
||||
|
||||
case FLM_TEXT_TYPE :
|
||||
{
|
||||
FLMUINT uiNumber = 0;
|
||||
|
||||
while( uiValueLength--)
|
||||
uiTotalNum = 0;
|
||||
if (*pucValue == '-')
|
||||
{
|
||||
*pbNegFlag = TRUE;
|
||||
uiMaxBeforeMultValue = ((FLMUINT)(FLM_MAX_INT) + 1) / 10;
|
||||
uiMaxValue = (FLMUINT)(FLM_MAX_INT) + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
*pbNegFlag = FALSE;
|
||||
uiMaxBeforeMultValue = (FLM_MAX_UINT) / 10;
|
||||
uiMaxValue = FLM_MAX_UINT;
|
||||
}
|
||||
while (uiValueLength--)
|
||||
{
|
||||
if( *pucValue < ASCII_ZERO || *pucValue > ASCII_NINE)
|
||||
{
|
||||
break;
|
||||
}
|
||||
uiByte = (FLMUINT)(*pucValue - ASCII_ZERO);
|
||||
|
||||
uiNumber = (uiNumber * 10) + (*pucValue - ASCII_ZERO);
|
||||
if (uiTotalNum > uiMaxBeforeMultValue)
|
||||
{
|
||||
if (*pbNegFlag)
|
||||
{
|
||||
rc = RC_SET( FERR_CONV_NUM_UNDERFLOW);
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = RC_SET( FERR_CONV_NUM_OVERFLOW);
|
||||
}
|
||||
goto Exit;
|
||||
}
|
||||
uiTotalNum = (uiTotalNum << 3) + (uiTotalNum << 1);
|
||||
if (uiTotalNum > uiMaxValue - uiByte)
|
||||
{
|
||||
if (*pbNegFlag)
|
||||
{
|
||||
rc = RC_SET( FERR_CONV_NUM_UNDERFLOW);
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = RC_SET( FERR_CONV_NUM_OVERFLOW);
|
||||
}
|
||||
goto Exit;
|
||||
}
|
||||
uiTotalNum += uiByte;
|
||||
pucValue++;
|
||||
}
|
||||
|
||||
bcd->uiNum = uiNumber;
|
||||
bcd->uiNibCnt = 0;
|
||||
bcd->bNegFlag = FALSE;
|
||||
*puiNum = uiTotalNum;
|
||||
break;
|
||||
}
|
||||
|
||||
case FLM_CONTEXT_TYPE :
|
||||
{
|
||||
if( uiValueLength == sizeof( FLMUINT32))
|
||||
if (uiValueLength == sizeof( FLMUINT32))
|
||||
{
|
||||
bcd->uiNum = (FLMUINT)( FB2UD( pucValue));
|
||||
|
||||
bcd->bNegFlag = 0;
|
||||
if( bcd->uiNum < FLM_MAX_UINT8)
|
||||
{
|
||||
bcd->uiNibCnt = 3;
|
||||
}
|
||||
else if( bcd->uiNum < FLM_MAX_UINT16)
|
||||
{
|
||||
bcd->uiNibCnt = 5;
|
||||
}
|
||||
else
|
||||
{
|
||||
bcd->uiNibCnt = 9;
|
||||
}
|
||||
*puiNum = (FLMUINT)( FB2UD( pucValue));
|
||||
*pbNegFlag = FALSE;
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -382,6 +678,186 @@ RCODE flmBcd2Num(
|
||||
return( RC_SET( FERR_CONV_ILLEGAL));
|
||||
}
|
||||
}
|
||||
|
||||
Exit:
|
||||
|
||||
return( FERR_OK);
|
||||
return( rc);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
Desc: Converts FT_NUMBER and FT_CONTEXT storage buffers to a 64 bit number
|
||||
****************************************************************************/
|
||||
RCODE flmBcd2Num64(
|
||||
FLMUINT uiValueType,
|
||||
FLMUINT uiValueLength,
|
||||
const FLMBYTE * pucValue,
|
||||
FLMUINT64 * pui64Num,
|
||||
FLMBOOL * pbNegFlag)
|
||||
{
|
||||
RCODE rc = FERR_OK;
|
||||
FLMUINT64 ui64TotalNum;
|
||||
FLMUINT uiByte;
|
||||
FLMUINT uiNibble;
|
||||
FLMUINT64 ui64MaxBeforeMultValue;
|
||||
FLMUINT64 ui64MaxValue;
|
||||
|
||||
if (pucValue == NULL)
|
||||
{
|
||||
rc = RC_SET( FERR_CONV_NULL_SRC);
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
switch (uiValueType)
|
||||
{
|
||||
case FLM_NUMBER_TYPE:
|
||||
{
|
||||
ui64TotalNum = 0;
|
||||
if ((*pucValue & 0xF0) == 0xB0)
|
||||
{
|
||||
*pbNegFlag = TRUE;
|
||||
uiNibble = 1;
|
||||
ui64MaxBeforeMultValue = ((FLMUINT64)(FLM_MAX_INT64) + 1) / 10;
|
||||
ui64MaxValue = (FLMUINT64)(FLM_MAX_INT64) + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
*pbNegFlag = FALSE;
|
||||
uiNibble = 0;
|
||||
ui64MaxBeforeMultValue = (FLM_MAX_UINT64) / 10;
|
||||
ui64MaxValue = FLM_MAX_UINT64;
|
||||
}
|
||||
|
||||
// Get each nibble and use to create the number
|
||||
|
||||
while (uiValueLength)
|
||||
{
|
||||
|
||||
// An odd value for uiNibble means we are on the 2nd nibble of
|
||||
// the byte.
|
||||
|
||||
if (uiNibble & 1)
|
||||
{
|
||||
uiByte = (FLMINT)(*pucValue & 0x0F);
|
||||
pucValue++;
|
||||
uiValueLength--;
|
||||
}
|
||||
else
|
||||
{
|
||||
uiByte = (FLMUINT)(*pucValue >> 4);
|
||||
}
|
||||
uiNibble++;
|
||||
if (uiByte == 0x0F)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (ui64TotalNum > ui64MaxBeforeMultValue)
|
||||
{
|
||||
if (*pbNegFlag)
|
||||
{
|
||||
rc = RC_SET( FERR_CONV_NUM_UNDERFLOW);
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = RC_SET( FERR_CONV_NUM_OVERFLOW);
|
||||
}
|
||||
goto Exit;
|
||||
}
|
||||
ui64TotalNum = (ui64TotalNum << 3) + (ui64TotalNum << 1);
|
||||
if (ui64TotalNum > ui64MaxValue - (FLMUINT64)uiByte)
|
||||
{
|
||||
if (*pbNegFlag)
|
||||
{
|
||||
rc = RC_SET( FERR_CONV_NUM_UNDERFLOW);
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = RC_SET( FERR_CONV_NUM_OVERFLOW);
|
||||
}
|
||||
goto Exit;
|
||||
}
|
||||
ui64TotalNum += (FLMUINT64)uiByte;
|
||||
}
|
||||
*pui64Num = ui64TotalNum;
|
||||
break;
|
||||
}
|
||||
|
||||
case FLM_TEXT_TYPE :
|
||||
{
|
||||
ui64TotalNum = 0;
|
||||
if (*pucValue == '-')
|
||||
{
|
||||
*pbNegFlag = TRUE;
|
||||
ui64MaxBeforeMultValue = ((FLMUINT64)(FLM_MAX_INT64) + 1) / 10;
|
||||
ui64MaxValue = (FLMUINT64)(FLM_MAX_INT64) + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
*pbNegFlag = FALSE;
|
||||
ui64MaxBeforeMultValue = (FLM_MAX_UINT64) / 10;
|
||||
ui64MaxValue = FLM_MAX_UINT64;
|
||||
}
|
||||
while (uiValueLength--)
|
||||
{
|
||||
if( *pucValue < ASCII_ZERO || *pucValue > ASCII_NINE)
|
||||
{
|
||||
break;
|
||||
}
|
||||
uiByte = (FLMUINT)(*pucValue - ASCII_ZERO);
|
||||
|
||||
if (ui64TotalNum > ui64MaxBeforeMultValue)
|
||||
{
|
||||
if (*pbNegFlag)
|
||||
{
|
||||
rc = RC_SET( FERR_CONV_NUM_UNDERFLOW);
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = RC_SET( FERR_CONV_NUM_OVERFLOW);
|
||||
}
|
||||
goto Exit;
|
||||
}
|
||||
ui64TotalNum = (ui64TotalNum << 3) + (ui64TotalNum << 1);
|
||||
if (ui64TotalNum > ui64MaxValue - (FLMUINT64)uiByte)
|
||||
{
|
||||
if (*pbNegFlag)
|
||||
{
|
||||
rc = RC_SET( FERR_CONV_NUM_UNDERFLOW);
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = RC_SET( FERR_CONV_NUM_OVERFLOW);
|
||||
}
|
||||
goto Exit;
|
||||
}
|
||||
ui64TotalNum += (FLMUINT64)uiByte;
|
||||
pucValue++;
|
||||
}
|
||||
|
||||
*pui64Num = ui64TotalNum;
|
||||
break;
|
||||
}
|
||||
|
||||
case FLM_CONTEXT_TYPE :
|
||||
{
|
||||
if (uiValueLength == sizeof( FLMUINT32))
|
||||
{
|
||||
*pui64Num = (FLMUINT64)( FB2UD( pucValue));
|
||||
*pbNegFlag = FALSE;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
flmAssert( 0);
|
||||
return( RC_SET( FERR_CONV_ILLEGAL));
|
||||
}
|
||||
}
|
||||
|
||||
Exit:
|
||||
|
||||
return( rc);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user