From 24346739dd48b109a3740436abc4af0467fa65eb Mon Sep 17 00:00:00 2001 From: dsandersoremutah Date: Fri, 1 Sep 2006 16:34:15 +0000 Subject: [PATCH] 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 --- flaim/Makefile | 4 +- flaim/src/fcs.cpp | 210 +++- flaim/src/fcs.h | 4 +- flaim/src/fgedcom.cpp | 421 ++++--- flaim/src/flaim.h | 97 +- flaim/src/flaimsys.h | 39 +- flaim/src/flchkdb.cpp | 4 +- flaim/src/flverify.cpp | 30 +- flaim/src/fnumber.cpp | 752 +++++++++--- flaim/src/fqdecl.cpp | 23 + flaim/src/fqeval.cpp | 2337 +++++++++++++++++++++---------------- flaim/src/fqkeys.cpp | 136 +-- flaim/src/fqlog.cpp | 8 + flaim/src/fqopt.cpp | 6 +- flaim/src/fqparse.cpp | 258 +++- flaim/src/fqprep.cpp | 12 + flaim/src/fqstack.cpp | 29 +- flaim/src/fquery.h | 19 +- flaim/src/frebuild.cpp | 4 +- flaim/src/frec.cpp | 280 ++++- flaim/src/fsrecupd.cpp | 2 +- flaim/src/fstructs.h | 12 - flaim/src/fsv.cpp | 18 +- flaim/src/imonqury.cpp | 8 + flaim/src/kybuild.cpp | 124 +- flaim/src/scache.cpp | 2 +- flaim/util/basic_test.cpp | 1105 ++++++++++++++++++ 27 files changed, 4376 insertions(+), 1568 deletions(-) diff --git a/flaim/Makefile b/flaim/Makefile index 4559b6a..b6c0504 100644 --- a/flaim/Makefile +++ b/flaim/Makefile @@ -56,8 +56,8 @@ version = $(major_version).$(minor_version).$(svn_revision) # 5. If any interfaces have been added since the last public release, increment age # 6. If any interfaces have been removed since the last public release, set age to 0 -so_current = 3 -so_revision = 0 +so_current = 4 +so_revision = 1 so_age = 0 shared_lib_version = diff --git a/flaim/src/fcs.cpp b/flaim/src/fcs.cpp index 637b2b5..082dce2 100644 --- a/flaim/src/fcs.cpp +++ b/flaim/src/fcs.cpp @@ -1173,6 +1173,55 @@ RCODE FCS_DIS::readHTD( break; } + + case HTD_TYPE_UINT64: + { + FLMUINT64 ui64Value; + + if( pNode) + { + GedValTypeSet( pNode, FLM_NUMBER_TYPE); + } + + if( ppRecord) + { + if( RC_BAD( rc = (*ppRecord)->insertLast( ucLevel, + ui16Tag, FLM_NUMBER_TYPE, &pField))) + { + goto Exit; + } + } + + if( !bHasValue) + { + break; + } + + // Read an unsigned 64-bit integer. + + if( RC_BAD( rc = readUInt64( &ui64Value))) + { + goto Exit; + } + + if( pNode) + { + if( RC_BAD( rc = GedPutUINT64( pPool, pNode, ui64Value))) + { + goto Exit; + } + } + + if( ppRecord) + { + if( RC_BAD( rc = (*ppRecord)->setUINT64( pField, ui64Value))) + { + goto Exit; + } + } + + break; + } case HTD_TYPE_INT: { @@ -1223,6 +1272,55 @@ RCODE FCS_DIS::readHTD( break; } + case HTD_TYPE_INT64: + { + FLMINT64 i64Value; + + if( pNode) + { + GedValTypeSet( pNode, FLM_NUMBER_TYPE); + } + + if( ppRecord) + { + if( RC_BAD( rc = (*ppRecord)->insertLast( ucLevel, + ui16Tag, FLM_NUMBER_TYPE, &pField))) + { + goto Exit; + } + } + + if( !bHasValue) + { + break; + } + + // Read a signed 64-bit integer. + + if( RC_BAD( rc = readInt64( &i64Value))) + { + goto Exit; + } + + if( pNode) + { + if( RC_BAD( rc = GedPutINT64( pPool, pNode, i64Value))) + { + goto Exit; + } + } + + if( ppRecord) + { + if( RC_BAD( rc = (*ppRecord)->setINT64( pField, i64Value))) + { + goto Exit; + } + } + + break; + } + case HTD_TYPE_CONTEXT: { FLMUINT32 ui32Value; @@ -1945,11 +2043,44 @@ RCODE FCS_DOS::writeHTD( if( ((*pucCurData & 0xF0) == 0xB0)) { - uiDescriptor |= HTD_TYPE_INT; + FLMINT64 i64Value; + + if( (pCurNode && RC_BAD( rc = GedGetINT64( + pCurNode, &i64Value))) || + (pCurField && RC_BAD( rc = pRecord->getINT64( + pCurField, &i64Value)))) + { + goto Exit; + } + if (i64Value >= (FLMINT64)(FLM_MIN_INT32) && + i64Value <= (FLMINT64)(FLM_MAX_INT32)) + { + uiDescriptor |= HTD_TYPE_INT; + } + else + { + uiDescriptor |= HTD_TYPE_INT64; + } } else { - uiDescriptor |= HTD_TYPE_UINT; + FLMUINT64 ui64Value; + + if( (pCurNode && RC_BAD( rc = GedGetUINT64( + pCurNode, &ui64Value))) || + (pCurField && RC_BAD( rc = pRecord->getUINT64( + pCurField, &ui64Value)))) + { + goto Exit; + } + if (ui64Value <= (FLMUINT64)(FLM_MAX_UINT32)) + { + uiDescriptor |= HTD_TYPE_UINT; + } + else + { + uiDescriptor |= HTD_TYPE_UINT64; + } } break; } @@ -2147,45 +2278,90 @@ RCODE FCS_DOS::writeHTD( { if( uiCurDataLen) { - if( uiDescriptor & HTD_TYPE_INT) + if( uiDescriptor & HTD_TYPE_INT64) { // Since the number is negative, extract and send it - // as a signed 32-bit value. + // as a signed 64-bit value. - FLMINT iValue; + FLMINT64 i64Value; - if( (pCurNode && RC_BAD( rc = GedGetINT( - pCurNode, &iValue))) || - (pCurField && RC_BAD( rc = pRecord->getINT( - pCurField, &iValue)))) + if( (pCurNode && RC_BAD( rc = GedGetINT64( + pCurNode, &i64Value))) || + (pCurField && RC_BAD( rc = pRecord->getINT64( + pCurField, &i64Value)))) { goto Exit; } // Write the value. - if( RC_BAD( rc = writeInt32( (FLMINT32)iValue))) + if( RC_BAD( rc = writeInt64( i64Value))) + { + goto Exit; + } + } + else if( uiDescriptor & HTD_TYPE_INT) + { + // Since the number is negative, extract and send it + // as a signed 32-bit value. + + FLMINT32 i32Value; + + if( (pCurNode && RC_BAD( rc = GedGetINT32( + pCurNode, &i32Value))) || + (pCurField && RC_BAD( rc = pRecord->getINT32( + pCurField, &i32Value)))) + { + goto Exit; + } + + // Write the value. + + if( RC_BAD( rc = writeInt32( i32Value))) + { + goto Exit; + } + } + else if( uiDescriptor & HTD_TYPE_UINT64) + { + // The number is non-negative 64 bit + + FLMUINT64 ui64Value; + + if( (pCurNode && RC_BAD( rc = GedGetUINT64( + pCurNode, &ui64Value))) || + (pCurField && RC_BAD( rc = pRecord->getUINT64( + pCurField, &ui64Value)))) + { + goto Exit; + } + + // Write the value. + + if( RC_BAD( rc = writeUInt64( ui64Value))) { goto Exit; } } else { - // The number is non-negative + flmAssert( uiDescriptor & HTD_TYPE_UINT); + + // The number is non-negative 32 bit - FLMUINT uiValue; + FLMUINT32 ui32Value; - if( (pCurNode && RC_BAD( rc = GedGetUINT( - pCurNode, &uiValue))) || - (pCurField && RC_BAD( rc = pRecord->getUINT( - pCurField, &uiValue)))) + if( (pCurNode && RC_BAD( rc = GedGetUINT32( + pCurNode, &ui32Value))) || + (pCurField && RC_BAD( rc = pRecord->getUINT32( + pCurField, &ui32Value)))) { goto Exit; } // Write the value. - if( RC_BAD( rc = writeUInt32( (FLMUINT32)uiValue))) + if( RC_BAD( rc = writeUInt32( ui32Value))) { goto Exit; } diff --git a/flaim/src/fcs.h b/flaim/src/fcs.h index 2a0377a..92c3be1 100644 --- a/flaim/src/fcs.h +++ b/flaim/src/fcs.h @@ -356,8 +356,8 @@ #define HTD_TYPE_TMSTAMP ((FLMUINT) 0x09) #define HTD_TYPE_BLOB ((FLMUINT) 0x0A) #define HTD_TYPE_GEDCOM ((FLMUINT) 0x0B) -#define HTD_TYPE_RESERVED_1 ((FLMUINT) 0x1C) -#define HTD_TYPE_RESERVED_2 ((FLMUINT) 0x1D) +#define HTD_TYPE_UINT64 ((FLMUINT) 0x1C) +#define HTD_TYPE_INT64 ((FLMUINT) 0x1D) #define HTD_TYPE_RESERVED_3 ((FLMUINT) 0x1E) #define HTD_TYPE_RESERVED_4 ((FLMUINT) 0x1F) diff --git a/flaim/src/fgedcom.cpp b/flaim/src/fgedcom.cpp index a778f6a..3537e35 100644 --- a/flaim/src/fgedcom.cpp +++ b/flaim/src/fgedcom.cpp @@ -25,9 +25,6 @@ #include "flaimsys.h" extern FLMBYTE arr[]; -extern FLMBYTE ucMaxBcdINT32[]; -extern FLMBYTE ucMinBcdINT32[]; -extern FLMBYTE ucMaxBcdUINT32[]; #define BINARY_GED_HEADER_LEN 8 @@ -1547,53 +1544,77 @@ RCODE GedPutUINT( { RCODE rc = FERR_OK; FLMBYTE * pucPtr; - FLMBYTE ucNibStk[F_MAX_NUM_BUF + 1]; - FLMBYTE * pucNibStk; - + FLMBYTE ucStorageBuf[F_MAX_NUM_BUF + 1]; + FLMUINT uiStorageLen; + if (pNode == NULL) { rc = RC_SET( FERR_CONV_NULL_DEST); goto Exit; } - // push spare (undefined) nibble for possible half-used terminating - // byte - - pucNibStk = &ucNibStk[1]; - - // push terminator nibble -- popped last - - *pucNibStk++ = 0x0F; - - // push digits; - // do 32 bit division until we get down to 16 bits - - while (uiNum >= 10) + uiStorageLen = sizeof( ucStorageBuf); + if( RC_BAD( rc = FlmUINT2Storage( uiNum, &uiStorageLen, ucStorageBuf))) { - *pucNibStk++ = (FLMBYTE) (uiNum % 10); // push BCD nibbles in reverse - // order - uiNum /= 10; + goto Exit; } - *pucNibStk++ = (FLMBYTE) uiNum; // push last nibble of number - - // Determine number of bytes required for BCD number & allocate space + // Allocate the needed space. if ((pucPtr = (FLMBYTE *) GedAllocSpace( pPool, pNode, FLM_NUMBER_TYPE, - ((pucNibStk - ucNibStk) >> 1), uiEncId, uiEncSize)) == NULL) + uiStorageLen, uiEncId, uiEncSize)) == NULL) { rc = RC_SET( FERR_MEM); goto Exit; } + f_memcpy( pucPtr, ucStorageBuf, uiStorageLen); - // Pop stack and pack nibbles into byte stream a pair at a time - - do + if (pNode->ui32EncId) { - *pucPtr++ = (FLMBYTE) ((pucNibStk[-1] << 4) | pucNibStk[-2]); - } while ((pucNibStk -= 2) > &ucNibStk[1]); + pNode->ui32EncFlags = FLD_HAVE_DECRYPTED_DATA; + } - // spare stack byte stops seg wrap +Exit: + + return (rc); +} + +/***************************************************************************** +Desc: +*****************************************************************************/ +RCODE GedPutUINT64( + F_Pool * pPool, + NODE * pNode, + FLMUINT64 ui64Num, + FLMUINT uiEncId, + FLMUINT uiEncSize) +{ + RCODE rc = FERR_OK; + FLMBYTE * pucPtr; + FLMBYTE ucStorageBuf[F_MAX_NUM64_BUF + 1]; + FLMUINT uiStorageLen; + + if (pNode == NULL) + { + rc = RC_SET( FERR_CONV_NULL_DEST); + goto Exit; + } + + uiStorageLen = sizeof( ucStorageBuf); + if( RC_BAD( rc = FlmUINT64ToStorage( ui64Num, &uiStorageLen, ucStorageBuf))) + { + goto Exit; + } + + // Allocate the needed space. + + if ((pucPtr = (FLMBYTE *) GedAllocSpace( pPool, pNode, FLM_NUMBER_TYPE, + uiStorageLen, uiEncId, uiEncSize)) == NULL) + { + rc = RC_SET( FERR_MEM); + goto Exit; + } + f_memcpy( pucPtr, ucStorageBuf, uiStorageLen); if (pNode->ui32EncId) { @@ -1616,11 +1637,9 @@ RCODE GedPutINT( FLMUINT uiEncSize) { RCODE rc = FERR_OK; - FLMUINT uiNum; FLMBYTE * pucPtr; - FLMBYTE ucNibStk[ F_MAX_NUM_BUF + 1]; - FLMBYTE * pucNibStk; - FLMINT iNegFlag; + FLMBYTE ucStorageBuf[F_MAX_NUM_BUF + 1]; + FLMUINT uiStorageLen; if (!pNode) { @@ -1628,40 +1647,68 @@ RCODE GedPutINT( goto Exit; } - pucNibStk = &ucNibStk[1]; - *pucNibStk++ = 0x0F; - uiNum = ((iNegFlag = iNum < 0) != 0) ? -iNum : iNum; - - while (uiNum >= 10) + uiStorageLen = sizeof( ucStorageBuf); + if( RC_BAD( rc = FlmINT2Storage( iNum, &uiStorageLen, ucStorageBuf))) { - *pucNibStk++ = (FLMBYTE) (uiNum % 10); - uiNum /= 10; + goto Exit; } - - *pucNibStk++ = (FLMBYTE) uiNum; - - if (iNegFlag) - { - *pucNibStk++ = 0x0B; - } - + // Determine number of bytes required for BCD number & allocate space if ((pucPtr = (FLMBYTE *) GedAllocSpace( pPool, pNode, FLM_NUMBER_TYPE, - ((pucNibStk - ucNibStk) >> 1), uiEncId, uiEncSize)) == NULL) + uiStorageLen, uiEncId, uiEncSize)) == NULL) { rc = RC_SET( FERR_MEM); goto Exit; } + f_memcpy( pucPtr, ucStorageBuf, uiStorageLen); - // Pop stack and pack nibbles into byte stream a pair at a time - - do + if (pNode->ui32EncId) { - *pucPtr++ = (FLMBYTE) ((pucNibStk[-1] << 4) | pucNibStk[-2]); - } while ((pucNibStk -= 2) > &ucNibStk[1]); + pNode->ui32EncFlags = FLD_HAVE_DECRYPTED_DATA; + } - // spare stack byte stops seg wrap +Exit: + + return (rc); +} + +/***************************************************************************** +Desc: +*****************************************************************************/ +RCODE GedPutINT64( + F_Pool * pPool, + NODE * pNode, + FLMINT64 i64Num, + FLMUINT uiEncId, + FLMUINT uiEncSize) +{ + RCODE rc = FERR_OK; + FLMBYTE * pucPtr; + FLMBYTE ucStorageBuf[F_MAX_NUM64_BUF + 1]; + FLMUINT uiStorageLen; + + if (!pNode) + { + rc = RC_SET( FERR_CONV_NULL_DEST); + goto Exit; + } + + uiStorageLen = sizeof( ucStorageBuf); + if( RC_BAD( rc = FlmINT64ToStorage( i64Num, &uiStorageLen, ucStorageBuf))) + { + goto Exit; + } + + // Determine number of bytes required for BCD number & allocate space + + if ((pucPtr = (FLMBYTE *) GedAllocSpace( pPool, pNode, FLM_NUMBER_TYPE, + uiStorageLen, uiEncId, uiEncSize)) == NULL) + { + rc = RC_SET( FERR_MEM); + goto Exit; + } + f_memcpy( pucPtr, ucStorageBuf, uiStorageLen); if (pNode->ui32EncId) { @@ -1680,8 +1727,7 @@ RCODE GedGetINT( NODE * pNode, FLMINT * piNum) { - RCODE rc = FERR_OK; - BCD_TYPE bcd; + RCODE rc = FERR_OK; if (pNode->ui32EncId) { @@ -1692,29 +1738,39 @@ RCODE GedGetINT( } } - if (RC_BAD( rc = flmBcd2Num( GedValType( pNode), GedValLen( pNode), - (const FLMBYTE *) GedValPtr( pNode), &bcd))) + if (RC_BAD( rc = FlmStorage2INT( GedValType( pNode), GedValLen( pNode), + (const FLMBYTE *) GedValPtr( pNode), piNum))) { goto Exit; } - if (bcd.bNegFlag) +Exit: + + return (rc); +} + +/***************************************************************************** +Desc: +*****************************************************************************/ +RCODE GedGetINT64( + NODE * pNode, + FLMINT64 * pi64Num) +{ + RCODE rc = FERR_OK; + + if (pNode->ui32EncId) { - *piNum = -((FLMINT) bcd.uiNum); - rc = (bcd.uiNibCnt < 11) || - (bcd.uiNibCnt == 11 && (!bcd.pucPtr || - (f_memcmp( bcd.pucPtr, ucMinBcdINT32, 6) <= 0))) - ? FERR_OK - : RC_SET( FERR_CONV_NUM_UNDERFLOW); + if (!(pNode->ui32EncFlags & FLD_HAVE_DECRYPTED_DATA)) + { + rc = RC_SET( FERR_FLD_NOT_DECRYPTED); + goto Exit; + } } - else + + if (RC_BAD( rc = FlmStorage2INT64( GedValType( pNode), GedValLen( pNode), + (const FLMBYTE *) GedValPtr( pNode), pi64Num))) { - *piNum = (FLMINT) bcd.uiNum; - rc = (bcd.uiNibCnt < 10) || - (bcd.uiNibCnt == 10 && (!bcd.pucPtr || - (f_memcmp( bcd.pucPtr, ucMaxBcdINT32, 5) <= 0))) - ? FERR_OK - : RC_SET( FERR_CONV_NUM_OVERFLOW); + goto Exit; } Exit: @@ -1729,8 +1785,7 @@ RCODE GedGetINT32( NODE * pNode, FLMINT32 * pi32Num) { - RCODE rc = FERR_OK; - BCD_TYPE bcd; + RCODE rc = FERR_OK; if (pNode->ui32EncId) { @@ -1741,27 +1796,10 @@ RCODE GedGetINT32( } } - if (RC_OK( rc = flmBcd2Num( GedValType( pNode), GedValLen( pNode), - (const FLMBYTE *) GedValPtr( pNode), &bcd))) + if (RC_BAD( rc = FlmStorage2INT32( GedValType( pNode), GedValLen( pNode), + (const FLMBYTE *)GedValPtr( pNode), pi32Num))) { - if (bcd.bNegFlag) - { - *pi32Num = -((FLMINT32) bcd.uiNum); - rc = (bcd.uiNibCnt < 11) || - (bcd.uiNibCnt == 11 && (!bcd.pucPtr || - (f_memcmp( bcd.pucPtr, ucMinBcdINT32, 6) <= 0))) - ? FERR_OK - : RC_SET( FERR_CONV_NUM_UNDERFLOW); - } - else - { - *pi32Num = (FLMINT32) bcd.uiNum; - rc = (bcd.uiNibCnt < 10) || - (bcd.uiNibCnt == 10 && - (!bcd.pucPtr || (f_memcmp( bcd.pucPtr, ucMaxBcdINT32, 5) <= 0))) - ? FERR_OK - : RC_SET( FERR_CONV_NUM_OVERFLOW); - } + goto Exit; } Exit: @@ -1776,8 +1814,9 @@ RCODE GedGetINT16( NODE * pNode, FLMINT16 * pi16Num) { - RCODE rc = FERR_OK; - BCD_TYPE bcd; + RCODE rc = FERR_OK; + FLMUINT uiNum; + FLMBOOL bNegFlag; if (pNode->ui32EncId) { @@ -1789,21 +1828,36 @@ RCODE GedGetINT16( } if (RC_OK( rc = flmBcd2Num( GedValType( pNode), GedValLen( pNode), - (const FLMBYTE *) GedValPtr( pNode), &bcd))) + (const FLMBYTE *) GedValPtr( pNode), &uiNum, &bNegFlag))) { - if (bcd.bNegFlag) + if (bNegFlag) { - *pi16Num = -((FLMINT16) (bcd.uiNum)); - rc = (bcd.uiNibCnt < 6) || (bcd.uiNibCnt == 6 && bcd.uiNum <= FLM_MAX_INT16) - ? FERR_OK - : RC_SET( FERR_CONV_NUM_UNDERFLOW); + + // We will have checked to make sure we are not less than + // -(FLM_MAX_INT + 1), but this is smaller than + // than -(FLM_MAX_INT16 + 1), + // so we need to check to make sure we are not less than + // -(FLM_MAX_INT32 + 1) + + if (uiNum > (FLMUINT)(FLM_MAX_INT16) + 1) + { + rc = RC_SET( FERR_CONV_NUM_UNDERFLOW); + goto Exit; + } + *pi16Num = -((FLMINT16)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_INT16. + + else if (uiNum > (FLMUINT)(FLM_MAX_INT16)) + { + rc = RC_SET( FERR_CONV_NUM_OVERFLOW); + goto Exit; } else { - *pi16Num = (FLMINT16) bcd.uiNum; - rc = (bcd.uiNibCnt < 5) || (bcd.uiNibCnt == 5 && bcd.uiNum < FLM_MAX_INT16) - ? FERR_OK - : RC_SET( FERR_CONV_NUM_OVERFLOW); + *pi16Num = (FLMINT16)uiNum; } } @@ -1819,8 +1873,7 @@ RCODE GedGetUINT( NODE * pNode, FLMUINT * puiNum) { - RCODE rc = FERR_OK; - BCD_TYPE bcd; + RCODE rc = FERR_OK; if (pNode->ui32EncId) { @@ -1831,30 +1884,10 @@ RCODE GedGetUINT( } } - if (RC_OK( rc = flmBcd2Num( GedValType( pNode), GedValLen( pNode), - (const FLMBYTE *) GedValPtr( pNode), &bcd))) + if (RC_BAD( rc = FlmStorage2UINT( GedValType( pNode), GedValLen( pNode), + (const FLMBYTE *) GedValPtr( pNode), puiNum))) { - *puiNum = bcd.uiNum; - - if (bcd.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); - } + goto Exit; } Exit: @@ -1869,8 +1902,9 @@ RCODE GedGetUINT8( NODE * pNode, FLMUINT8 * pui8Num) { - RCODE rc = FERR_OK; - BCD_TYPE bcd; + RCODE rc = FERR_OK; + FLMUINT uiNum; + FLMBOOL bNegFlag; if (pNode->ui32EncId) { @@ -1882,15 +1916,49 @@ RCODE GedGetUINT8( } if (RC_OK( rc = flmBcd2Num( GedValType( pNode), GedValLen( pNode), - (const FLMBYTE *) GedValPtr( pNode), &bcd))) + (const FLMBYTE *) GedValPtr( pNode), &uiNum, &bNegFlag))) { - *pui8Num = (FLMUINT8) bcd.uiNum; - rc = bcd.bNegFlag - ? RC_SET( FERR_CONV_NUM_UNDERFLOW) - : (bcd.uiNibCnt < 3) || - (bcd.uiNibCnt == 3 && bcd.uiNum < FLM_MAX_UINT8) - ? FERR_OK - : RC_SET( FERR_CONV_NUM_OVERFLOW); + if (bNegFlag) + { + rc = RC_SET( FERR_CONV_NUM_UNDERFLOW); + } + else if (uiNum > (FLMUINT)(FLM_MAX_UINT8)) + { + rc = RC_SET( FERR_CONV_NUM_OVERFLOW); + } + else + { + *pui8Num = (FLMUINT8)uiNum; + } + } + +Exit: + + return (rc); +} + +/***************************************************************************** +Desc: +*****************************************************************************/ +RCODE GedGetUINT64( + NODE * pNode, + FLMUINT64 * pui64Num) +{ + RCODE rc = FERR_OK; + + if (pNode->ui32EncId) + { + if (!(pNode->ui32EncFlags & FLD_HAVE_DECRYPTED_DATA)) + { + rc = RC_SET( FERR_FLD_NOT_DECRYPTED); + goto Exit; + } + } + + if (RC_BAD( rc = FlmStorage2UINT64( GedValType( pNode), GedValLen( pNode), + (const FLMBYTE *) GedValPtr( pNode), pui64Num))) + { + goto Exit; } Exit: @@ -1905,8 +1973,7 @@ RCODE GedGetUINT32( NODE * pNode, FLMUINT32 * pui32Num) { - RCODE rc = FERR_OK; - BCD_TYPE bcd; + RCODE rc = FERR_OK; if (pNode->ui32EncId) { @@ -1917,29 +1984,10 @@ RCODE GedGetUINT32( } } - if (RC_OK( rc = flmBcd2Num( GedValType( pNode), GedValLen( pNode), - (const FLMBYTE *) GedValPtr( pNode), &bcd))) + if (RC_BAD( rc = FlmStorage2UINT32( GedValType( pNode), GedValLen( pNode), + (const FLMBYTE *) GedValPtr( pNode), pui32Num))) { - *pui32Num = (FLMUINT32) bcd.uiNum; - - if (bcd.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); - } + goto Exit; } Exit: @@ -1954,8 +2002,9 @@ RCODE GedGetUINT16( NODE * pNode, FLMUINT16 * pui16Num) { - BCD_TYPE bcd; - RCODE rc = FERR_OK; + RCODE rc = FERR_OK; + FLMUINT uiNum; + FLMBOOL bNegFlag; if (pNode->ui32EncId) { @@ -1967,15 +2016,20 @@ RCODE GedGetUINT16( } if (RC_OK( rc = flmBcd2Num( GedValType( pNode), GedValLen( pNode), - (const FLMBYTE *) GedValPtr( pNode), &bcd)) == FERR_OK) + (const FLMBYTE *) GedValPtr( pNode), &uiNum, &bNegFlag))) { - *pui16Num = (FLMUINT16) bcd.uiNum; - rc = bcd.bNegFlag - ? RC_SET( FERR_CONV_NUM_UNDERFLOW) - : (bcd.uiNibCnt < 5) || - (bcd.uiNibCnt == 5 && bcd.uiNum < FLM_MAX_UINT16) - ? FERR_OK - : RC_SET( FERR_CONV_NUM_OVERFLOW); + if (bNegFlag) + { + rc = RC_SET( FERR_CONV_NUM_UNDERFLOW); + } + else if (uiNum > (FLMUINT)(FLM_MAX_UINT16)) + { + rc = RC_SET( FERR_CONV_NUM_OVERFLOW); + } + else + { + *pui16Num = (FLMUINT16)uiNum; + } } Exit: @@ -3197,23 +3251,28 @@ RCODE gedAddField( { case 0: uiNum = (FLMUINT)(*((FLMUINT *)(pvData))); + rc = GedPutUINT( pPool, pChildNode, uiNum); break; case 1: uiNum = (FLMUINT)(*((FLMBYTE *)(pvData))); + rc = GedPutUINT( pPool, pChildNode, uiNum); break; case 2: uiNum = (FLMUINT)(*((FLMUINT16 *)(pvData))); + rc = GedPutUINT( pPool, pChildNode, uiNum); break; case 4: uiNum = (FLMUINT)(*((FLMUINT32 *)(pvData))); + rc = GedPutUINT( pPool, pChildNode, uiNum); + break; + case 8: + rc = GedPutUINT64( pPool, pChildNode, *((FLMUINT64 *)(pvData))); break; default: flmAssert( 0); rc = RC_SET( FERR_INVALID_PARM); goto Exit; } - - rc = GedPutUINT( pPool, pChildNode, uiNum); break; } diff --git a/flaim/src/flaim.h b/flaim/src/flaim.h index 8e024f1..b93bfac 100644 --- a/flaim/src/flaim.h +++ b/flaim/src/flaim.h @@ -149,7 +149,7 @@ #define FERR_BAD_RFL_FILE_NUMBER 0xC014 ///< 0xC014 - Bad RFL file number in RFL file header. #define FERR_CANNOT_DEL_ITEM 0xC015 ///< 0xC015 - Cannot delete field definitions. #define FERR_CANNOT_MOD_FIELD_TYPE 0xC016 ///< 0xC016 - Cannot modify a field's type. - #define FERR_NOT_USED_C017 0xC017 ///< 0xC017 - Not used + #define FERR_64BIT_NUMS_NOT_SUPPORTED 0xC017 ///< 0xC017 - 64 bit numbers not supported for databases whose revision is less than 462 #define FERR_CONV_BAD_DEST_TYPE 0xC018 ///< 0xC018 - Bad destination type specified for conversion. #define FERR_CONV_BAD_DIGIT 0xC019 ///< 0xC019 - Non-numeric digit found in text to numeric conversion. #define FERR_CONV_BAD_SRC_TYPE 0xC01A ///< 0xC01A - Bad source type specified for conversion. @@ -417,8 +417,9 @@ #define FLM_FILE_FORMAT_VER_4_52 452 // Added ability to delete indexes in the background #define FLM_FILE_FORMAT_VER_4_60 460 // Added support for encrypted attributes #define FLM_FILE_FORMAT_VER_4_61 461 // Added support for RFL disk usage limits, large field values, and async I/O on Linux and Solaris - #define FLM_CUR_FILE_FORMAT_VER_NUM FLM_FILE_FORMAT_VER_4_61 - #define FLM_CUR_FILE_FORMAT_VER_STR "4.61" + #define FLM_FILE_FORMAT_VER_4_62 462 // Added support for 64 bit numbers + #define FLM_CUR_FILE_FORMAT_VER_NUM FLM_FILE_FORMAT_VER_4_62 + #define FLM_CUR_FILE_FORMAT_VER_STR "4.62" FLMUINT uiMinRflFileSize; ///< Minimum bytes per RFL file. #define DEFAULT_MIN_RFL_FILE_SIZE ((FLMUINT)100 * (FLMUINT)1024 * (FLMUINT)1024) @@ -1199,6 +1200,8 @@ FLM_INT32_VAL, ///< 3 - 32 bit signed integer value. FLM_REAL_VAL, ///< 4 - Real number value.\ NOTE: Not currently supported. FLM_REC_PTR_VAL, ///< 5 - DRN value. + FLM_UINT64_VAL, ///< 6 - 64 bit unsigned integer value. + FLM_INT64_VAL, ///< 7 - 64 bit signed integer value. FLM_BINARY_VAL = 9, ///< 9 - Binary value. FLM_STRING_VAL, ///< 10 - ASCII string value. FLM_UNICODE_VAL, ///< 11 - Unicode string value. @@ -3205,6 +3208,7 @@ } FlmLogMessageType; #define F_MAX_NUM_BUF 12 + #define F_MAX_NUM64_BUF 24 /// Convert a FLMUINT value to FLAIM's internal storage format for numbers. /// \ingroup storageconversion @@ -3215,6 +3219,15 @@ FLMBYTE * pucStorageBuf ///< Number converted to FLAIM's internal storage format is returned here. ); + /// Convert a FLMUINT64 value to FLAIM's internal storage format for numbers. + /// \ingroup storageconversion + FLMEXP RCODE FLMAPI FlmUINT64ToStorage( + FLMUINT64 ui64Num, ///< Number to convert. + FLMUINT * puiStorageLen, ///< On input, *puiStorageLen is the size of pucStorageBuf.\ It must be atleast F_MAX_NUM64_BUF + ///< bytes.\ On output *puiStorageLen is set to the number of bytes used in pucStorageBuf. + FLMBYTE * pucStorageBuf ///< Number converted to FLAIM's internal storage format is returned here. + ); + /// Convert a FLMINT value to FLAIM's internal storage format for numbers. /// \ingroup storageconversion FLMEXP RCODE FLMAPI FlmINT2Storage( @@ -3224,6 +3237,15 @@ FLMBYTE * pucStorageBuf ///< Number converted to FLAIM's internal storage format is returned here. ); + /// Convert a FLMINT64 value to FLAIM's internal storage format for numbers. + /// \ingroup storageconversion + FLMEXP RCODE FLMAPI FlmINT64ToStorage( + FLMINT64 i64Num, ///< Number to convert. + FLMUINT * puiStorageLen, ///< On input, *puiStorageLen is the size of pucStorageBuf.\ It must be atleast F_MAX_NUM64_BUF + ///< bytes.\ On output *puiStorageLen is set to the number of bytes used in pucStorageBuf. + FLMBYTE * pucStorageBuf ///< Number converted to FLAIM's internal storage format is returned here. + ); + /// Convert a value from FLAIM's internal format to a FLMUINT. Note that the value may be a FLM_NUMBER_TYPE, /// FLM_TEXT_TYPE, or FLM_CONTEXT_TYPE. /// \ingroup storageconversion @@ -3246,6 +3268,17 @@ FLMUINT32 * pui32Num ///< Converted number is returned here. ); + /// Convert a value from FLAIM's internal format to a FLMUINT64. Note that the value may be a FLM_NUMBER_TYPE, + /// FLM_TEXT_TYPE, or FLM_CONTEXT_TYPE. + /// \ingroup storageconversion + FLMEXP RCODE FLMAPI FlmStorage2UINT64( + FLMUINT uiValueType, ///< Data type of value being converted.\ May be FLM_NUMBER_TYPE, FLM_TEXT_TYPE, or + ///< FLM_CONTEXT_TYPE. + FLMUINT uiValueLength, ///< Length of value to be converted (in bytes). + const FLMBYTE * pucValue, ///< Value to be converted.\ Data is expected to be in FLAIM's internal format. + FLMUINT64 * pui64Num ///< Converted number is returned here. + ); + /// Convert a value from FLAIM's internal format to a FLMINT. Note that the value may be a FLM_NUMBER_TYPE, /// FLM_TEXT_TYPE, or FLM_CONTEXT_TYPE. /// \ingroup storageconversion @@ -3257,6 +3290,28 @@ FLMINT * puiNum ///< Converted number is returned here. ); + /// Convert a value from FLAIM's internal format to a FLMINT32. Note that the value may be a FLM_NUMBER_TYPE, + /// FLM_TEXT_TYPE, or FLM_CONTEXT_TYPE. + /// \ingroup storageconversion + FLMEXP RCODE FLMAPI FlmStorage2INT32( + FLMUINT uiValueType, ///< Data type of value being converted.\ May be FLM_NUMBER_TYPE, FLM_TEXT_TYPE, or + ///< FLM_CONTEXT_TYPE. + FLMUINT uiValueLength, ///< Length of value to be converted (in bytes). + const FLMBYTE * pucValue, ///< Value to be converted.\ Data is expected to be in FLAIM's internal format. + FLMINT32 * pui32Num ///< Converted number is returned here. + ); + + /// Convert a value from FLAIM's internal format to a FLMINT64. Note that the value may be a FLM_NUMBER_TYPE, + /// FLM_TEXT_TYPE, or FLM_CONTEXT_TYPE. + /// \ingroup storageconversion + FLMEXP RCODE FLMAPI FlmStorage2INT64( + FLMUINT uiValueType, ///< Data type of value being converted.\ May be FLM_NUMBER_TYPE, FLM_TEXT_TYPE, or + ///< FLM_CONTEXT_TYPE. + FLMUINT uiValueLength, ///< Length of value to be converted (in bytes). + const FLMBYTE * pucValue, ///< Value to be converted.\ Data is expected to be in FLAIM's internal format. + FLMINT64 * pui64Num ///< Converted number is returned here. + ); + /// Convert a unicode string to FLAIM's internal storage format. /// \ingroup storageconversion FLMEXP RCODE FLMAPI FlmUnicode2Storage( @@ -3847,6 +3902,18 @@ FLMINT * piNumber ///< Number is returned here. ); + /// Get a field's value as a FLMINT32. Data conversions will be done if the field is a FLM_CONTEXT_TYPE or FLM_TEXT_TYPE. + RCODE getINT32( + void * pvField, ///< Field whose value is to be retrieved (and converted if necessary). + FLMINT32 * pi32Number ///< Number is returned here. + ); + + /// Get a field's value as a FLMINT64. Data conversions will be done if the field is a FLM_CONTEXT_TYPE or FLM_TEXT_TYPE. + RCODE getINT64( + void * pvField, ///< Field whose value is to be retrieved (and converted if necessary). + FLMINT64 * pi64Number ///< Number is returned here. + ); + /// Get a field's value as a FLMUINT. Data conversions will be done if the field is a FLM_CONTEXT_TYPE or FLM_TEXT_TYPE. RCODE getUINT( void * pvField, ///< Field whose value is to be retrieved (and converted if necessary). @@ -3859,6 +3926,12 @@ FLMUINT32 * pui32Number ///< Number is returned here. ); + /// Get a field's value as a FLMUINT64. Data conversions will be done if the field is a FLM_CONTEXT_TYPE or FLM_TEXT_TYPE. + RCODE getUINT64( + void * pvField, ///< Field whose value is to be retrieved (and converted if necessary). + FLMUINT64 * pui64Number ///< Number is returned here. + ); + /// Get the number of bytes needed to retrieve a field's value as a unicode string. The value may be either /// a FLM_NUMBER_TYPE or a FLM_TEXT_TYPE. The length returned does NOT account for null-termination, so if the application is /// calling this routine to determine how big of a buffer to allocate, it should add 2 to the size returned from this routine. @@ -3991,6 +4064,15 @@ ///< encryption key for that encryption definition will be used to encrypt this value. ); + /// Set a field's value to a FLMINT64 value. The resulting data type for the field will be FLM_NUMBER_TYPE. + RCODE setINT64( + void * pvField, ///< Field whose value is to be set. + FLMINT64 i64Number, ///< Value to set. + FLMUINT uiEncId = 0 ///< Encryption ID.\ If zero, the value will not be encrypted.\ If non-zero, the number + ///< should be the ID of an encryption definition record in the data dictionary.\ The + ///< encryption key for that encryption definition will be used to encrypt this value. + ); + /// Set a field's value to a FLMUINT value. The resulting data type for the field will be FLM_NUMBER_TYPE. RCODE setUINT( void * pvField, ///< Field whose value is to be set. @@ -4000,6 +4082,15 @@ ///< encryption key for that encryption definition will be used to encrypt this value. ); + /// Set a field's value to a FLMUINT64 value. The resulting data type for the field will be FLM_NUMBER_TYPE. + RCODE setUINT64( + void * pvField, ///< Field whose value is to be set. + FLMUINT64 ui64Number, ///< Value to set. + FLMUINT uiEncId = 0 ///< Encryption ID.\ If zero, the value will not be encrypted.\ If non-zero, the number + ///< should be the ID of an encryption definition record in the data dictionary.\ The + ///< encryption key for that encryption definition will be used to encrypt this value. + ); + /// Set a field's value to a FLMUINT value. The resulting data type for the field will be FLM_CONTEXT_TYPE. RCODE setRecPointer( void * pvField, ///< Field whose value is to be set. diff --git a/flaim/src/flaimsys.h b/flaim/src/flaimsys.h index cf188a4..0669704 100644 --- a/flaim/src/flaimsys.h +++ b/flaim/src/flaimsys.h @@ -334,6 +334,10 @@ RCODE GedGetINT( NODE * node, FLMINT * piNumberRV); +RCODE GedGetINT64( + NODE * node, + FLMINT64 * pi64NumberRV); + RCODE GedGetINT32( NODE * node, FLMINT32 * pi32NumberRV); @@ -346,6 +350,10 @@ RCODE GedGetUINT( NODE * node, FLMUINT * puiNumberRV); +RCODE GedGetUINT64( + NODE * node, + FLMUINT64 * pui64NumberRV); + RCODE GedGetUINT32( NODE * node, FLMUINT32 * pui32NumberRV); @@ -402,6 +410,20 @@ RCODE GedPutUINT( FLMUINT uiEncId = 0, FLMUINT uiEncSize = 0); +RCODE GedPutUINT64( + F_Pool * pPool, + NODE * nd, + FLMUINT64 ui64Number, + FLMUINT uiEncId = 0, + FLMUINT uiEncSize = 0); + +RCODE GedPutINT64( + F_Pool * pPool, + NODE * nd, + FLMINT64 i64Number, + FLMUINT uiEncId = 0, + FLMUINT uiEncSize = 0); + RCODE GedGetUNICODE( NODE * node, FLMUNICODE * pUnicode, @@ -495,13 +517,19 @@ RCODE GedGetRecSource( FLMUINT * puiContainer, FLMUINT * puiRecId); -#define FLM_MAX_NIB_CNT 11 - RCODE flmBcd2Num( FLMUINT uiValueType, FLMUINT uiValueLength, - const FLMBYTE * pucValue, - BCD_TYPE * bcd); + const FLMBYTE * pucValue, + FLMUINT * puiNum, + FLMBOOL * pbNegFlag); + +RCODE flmBcd2Num64( + FLMUINT uiValueType, + FLMUINT uiValueLength, + const FLMBYTE * pucValue, + FLMUINT64 * pui64Num, + FLMBOOL * pbNegFlag); /**************************************************************************** Desc: These functions are used to parse GEDCOM buffers/files. They @@ -1792,6 +1820,7 @@ FINLINE RCODE flmCheckVersionNum( case FLM_FILE_FORMAT_VER_4_52: case FLM_FILE_FORMAT_VER_4_60: case FLM_FILE_FORMAT_VER_4_61: + case FLM_FILE_FORMAT_VER_4_62: break; default: if( uiVersionNum > FLM_CUR_FILE_FORMAT_VER_NUM) @@ -2088,10 +2117,12 @@ eCorruptionType flmVerifyTextField( FLMUINT uiTextLen); eCorruptionType flmVerifyNumberField( + STATE_INFO * pStateInfo, FLMBYTE * pNumber, FLMUINT uiNumberLen); eCorruptionType flmVerifyField( + STATE_INFO * pStateInfo, FLMBYTE * pField, FLMUINT uiFieldLen, FLMUINT uiFieldType); diff --git a/flaim/src/flchkdb.cpp b/flaim/src/flchkdb.cpp index f2c01a5..1c48e70 100644 --- a/flaim/src/flchkdb.cpp +++ b/flaim/src/flchkdb.cpp @@ -3101,7 +3101,7 @@ FSTATIC RCODE chkVerifyElmFields( { if (!pStateInfo->uiEncId) { - *peElmCorruptCode = flmVerifyField( pValue, + *peElmCorruptCode = flmVerifyField( pStateInfo, pValue, pStateInfo->uiFieldLen, pStateInfo->uiFieldType); } @@ -3118,7 +3118,7 @@ FSTATIC RCODE chkVerifyElmFields( goto Exit; } - *peElmCorruptCode = flmVerifyField( pData, + *peElmCorruptCode = flmVerifyField( pStateInfo, pData, pStateInfo->uiFieldLen, pStateInfo->uiFieldType); } else diff --git a/flaim/src/flverify.cpp b/flaim/src/flverify.cpp index 05c9bf5..93ee82f 100644 --- a/flaim/src/flverify.cpp +++ b/flaim/src/flverify.cpp @@ -402,6 +402,7 @@ eCorruptionType flmVerifyTextField( Desc: This routine verifies a number field. ****************************************************************************/ eCorruptionType flmVerifyNumberField( + STATE_INFO * pStateInfo, FLMBYTE * pNumber, FLMUINT uiNumberLen) { @@ -517,11 +518,23 @@ eCorruptionType flmVerifyNumberField( return (FLM_BAD_NUMBER_FIELD); } - // Numbers greater than 11 digits not yet supported. - - if (!bRealNumberFlag && (uiNibbleCount > 11)) + if (pStateInfo->uiVersionNum >= FLM_FILE_FORMAT_VER_4_62) { - return (FLM_BAD_NUMBER_FIELD); + // Numbers greater than 21 digits not yet supported. + + if (!bRealNumberFlag && (uiNibbleCount > 21)) + { + return (FLM_BAD_NUMBER_FIELD); + } + } + else + { + // Numbers greater than 11 digits not yet supported. + + if (!bRealNumberFlag && (uiNibbleCount > 11)) + { + return (FLM_BAD_NUMBER_FIELD); + } } } } @@ -666,9 +679,10 @@ FSTATIC eCorruptionType flmVerifyBlobField( Desc: ****************************************************************************/ eCorruptionType flmVerifyField( - FLMBYTE* pField, - FLMUINT uiFieldLen, - FLMUINT uiFieldType) + STATE_INFO * pStateInfo, + FLMBYTE* pField, + FLMUINT uiFieldLen, + FLMUINT uiFieldType) { if (((uiFieldLen) && (!pField)) || ((!uiFieldLen) && (pField))) { @@ -684,7 +698,7 @@ eCorruptionType flmVerifyField( case FLM_NUMBER_TYPE: { - return (flmVerifyNumberField( pField, uiFieldLen)); + return (flmVerifyNumberField( pStateInfo, pField, uiFieldLen)); } case FLM_BINARY_TYPE: diff --git a/flaim/src/fnumber.cpp b/flaim/src/fnumber.cpp index 4709e70..d64c911 100644 --- a/flaim/src/fnumber.cpp +++ b/flaim/src/fnumber.cpp @@ -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); +} + diff --git a/flaim/src/fqdecl.cpp b/flaim/src/fqdecl.cpp index 6480b9a..a81529e 100644 --- a/flaim/src/fqdecl.cpp +++ b/flaim/src/fqdecl.cpp @@ -296,6 +296,15 @@ FSTATIC RCODE flmSendCursorWhere( goto Exit; } break; + case FLM_UINT64_VAL: + if (RC_BAD( rc = gedAddField( pPool, pRootNode, + FCS_ITERATOR_NUMBER_VALUE, + (void *)&pQNode->pQAtom->val.ui64Val, + 8, FLM_NUMBER_TYPE))) + { + goto Exit; + } + break; case FLM_INT32_VAL: if ((pFldNode = GedNodeMake( pPool, FCS_ITERATOR_NUMBER_VALUE, @@ -310,6 +319,20 @@ FSTATIC RCODE flmSendCursorWhere( goto Exit; } break; + case FLM_INT64_VAL: + if ((pFldNode = GedNodeMake( pPool, + FCS_ITERATOR_NUMBER_VALUE, + &rc)) == NULL) + { + goto Exit; + } + GedChildGraft( pRootNode, pFldNode, GED_LAST); + if (RC_BAD( rc = GedPutINT64( pPool, pFldNode, + pQNode->pQAtom->val.i64Val))) + { + goto Exit; + } + break; case FLM_REC_PTR_VAL: if (RC_BAD( rc = gedAddField( pPool, pRootNode, FCS_ITERATOR_REC_PTR_VALUE, diff --git a/flaim/src/fqeval.cpp b/flaim/src/fqeval.cpp index c7010a4..12b07e0 100644 --- a/flaim/src/fqeval.cpp +++ b/flaim/src/fqeval.cpp @@ -24,6 +24,10 @@ #include "flaimsys.h" +#define IS_UNSIGNED( e) ((e) == FLM_UINT32_VAL || (e) == FLM_UINT64_VAL) + +#define IS_SIGNED( e) ((e) == FLM_INT32_VAL || (e) == FLM_INT64_VAL) + FSTATIC FLMUINT flmCurEvalTrueFalse( FQATOM * pElm); @@ -67,331 +71,996 @@ FSTATIC RCODE flmCurEvalLogicalOp( FLMBOOL bHaveKey, FQATOM * pResult); -FSTATIC RCODE OpSyntaxError( - FQATOM * pLhs, - FQATOM * pRhs, - FQATOM * pResult); - -FSTATIC RCODE OpUUBitAND( - FQATOM * pLhs, - FQATOM * pRhs, - FQATOM * pResult); - -FSTATIC RCODE OpUUBitOR( - FQATOM * pLhs, - FQATOM * pRhs, - FQATOM * pResult); - -FSTATIC RCODE OpUUBitXOR( - FQATOM * pLhs, - FQATOM * pRhs, - FQATOM * pResult); - -FSTATIC RCODE OpUUMult( - FQATOM * pLhs, - FQATOM * pRhs, - FQATOM * pResult); - -FSTATIC RCODE OpUSMult( - FQATOM * pLhs, - FQATOM * pRhs, - FQATOM * pResult); - -FSTATIC RCODE OpSSMult( - FQATOM * pLhs, - FQATOM * pRhs, - FQATOM * pResult); - -FSTATIC RCODE OpSUMult( - FQATOM * pLhs, - FQATOM * pRhs, - FQATOM * pResult); - -FSTATIC RCODE OpURMult( - FQATOM * pLhs, - FQATOM * pRhs, - FQATOM * pResult); - -FSTATIC RCODE OpRUMult( - FQATOM * pLhs, - FQATOM * pRhs, - FQATOM * pResult); - -FSTATIC RCODE OpSRMult( - FQATOM * pLhs, - FQATOM * pRhs, - FQATOM * pResult); - -FSTATIC RCODE OpRSMult( - FQATOM * pLhs, - FQATOM * pRhs, - FQATOM * pResult); - -FSTATIC RCODE OpRRMult( - FQATOM * pLhs, - FQATOM * pRhs, - FQATOM * pResult); - -FSTATIC RCODE OpUUDiv( - FQATOM * pLhs, - FQATOM * pRhs, - FQATOM * pResult); - -FSTATIC RCODE OpUSDiv( - FQATOM * pLhs, - FQATOM * pRhs, - FQATOM * pResult); - -FSTATIC RCODE OpSSDiv( - FQATOM * pLhs, - FQATOM * pRhs, - FQATOM * pResult); - -FSTATIC RCODE OpSUDiv( - FQATOM * pLhs, - FQATOM * pRhs, - FQATOM * pResult); - -FSTATIC RCODE OpURDiv( - FQATOM * pLhs, - FQATOM * pRhs, - FQATOM * pResult); - -FSTATIC RCODE OpRUDiv( - FQATOM * pLhs, - FQATOM * pRhs, - FQATOM * pResult); - -FSTATIC RCODE OpSRDiv( - FQATOM * pLhs, - FQATOM * pRhs, - FQATOM * pResult); - -FSTATIC RCODE OpRSDiv( - FQATOM * pLhs, - FQATOM * pRhs, - FQATOM * pResult); - -FSTATIC RCODE OpRRDiv( - FQATOM * pLhs, - FQATOM * pRhs, - FQATOM * pResult); - -FSTATIC RCODE OpUUMod( - FQATOM * pLhs, - FQATOM * pRhs, - FQATOM * pResult); - -FSTATIC RCODE OpUSMod( - FQATOM * pLhs, - FQATOM * pRhs, - FQATOM * pResult); - -FSTATIC RCODE OpSSMod( - FQATOM * pLhs, - FQATOM * pRhs, - FQATOM * pResult); - -FSTATIC RCODE OpSUMod( - FQATOM * pLhs, - FQATOM * pRhs, - FQATOM * pResult); - -FSTATIC RCODE OpUUPlus( - FQATOM * pLhs, - FQATOM * pRhs, - FQATOM * pResult); - -FSTATIC RCODE OpUSPlus( - FQATOM * pLhs, - FQATOM * pRhs, - FQATOM * pResult); - -FSTATIC RCODE OpSSPlus( - FQATOM * pLhs, - FQATOM * pRhs, - FQATOM * pResult); - -FSTATIC RCODE OpSUPlus( - FQATOM * pLhs, - FQATOM * pRhs, - FQATOM * pResult); - -FSTATIC RCODE OpURPlus( - FQATOM * pLhs, - FQATOM * pRhs, - FQATOM * pResult); - -FSTATIC RCODE OpRUPlus( - FQATOM * pLhs, - FQATOM * pRhs, - FQATOM * pResult); - -FSTATIC RCODE OpSRPlus( - FQATOM * pLhs, - FQATOM * pRhs, - FQATOM * pResult); - -FSTATIC RCODE OpRSPlus( - FQATOM * pLhs, - FQATOM * pRhs, - FQATOM * pResult); - -FSTATIC RCODE OpRRPlus( - FQATOM * pLhs, - FQATOM * pRhs, - FQATOM * pResult); - -FSTATIC RCODE OpUUMinus( - FQATOM * pLhs, - FQATOM * pRhs, - FQATOM * pResult); - -FSTATIC RCODE OpUSMinus( - FQATOM * pLhs, - FQATOM * pRhs, - FQATOM * pResult); - -FSTATIC RCODE OpSSMinus( - FQATOM * pLhs, - FQATOM * pRhs, - FQATOM * pResult); - -FSTATIC RCODE OpSUMinus( - FQATOM * pLhs, - FQATOM * pRhs, - FQATOM * pResult); - -FSTATIC RCODE OpURMinus( - FQATOM * pLhs, - FQATOM * pRhs, - FQATOM * pResult); - -FSTATIC RCODE OpRUMinus( - FQATOM * pLhs, - FQATOM * pRhs, - FQATOM * pResult); - -FSTATIC RCODE OpSRMinus( - FQATOM * pLhs, - FQATOM * pRhs, - FQATOM * pResult); - -FSTATIC RCODE OpRSMinus( - FQATOM * pLhs, - FQATOM * pRhs, - FQATOM * pResult); - -FSTATIC RCODE OpRRMinus( - FQATOM * pLhs, - FQATOM * pRhs, - FQATOM * pResult); - #define IS_EXPORT_PTR(e) \ ((e) == FLM_TEXT_VAL || (e) == FLM_BINARY_VAL) -/**************************************************************************** -Desc: -****************************************************************************/ -FQ_OPERATION * FQ_DoOperation[((LAST_ARITH_OP - FIRST_ARITH_OP) + 1) * 9] = -{ - // BITAND +FSTATIC void fqOpUUBitAND( + FQATOM * pLValue, + FQATOM * pRValue, + FQATOM * pResult); + +FSTATIC void fqOpUUBitOR( + FQATOM * pLValue, + FQATOM * pRValue, + FQATOM * pResult); + +FSTATIC void fqOpUUBitXOR( + FQATOM * pLValue, + FQATOM * pRValue, + FQATOM * pResult); + +FSTATIC void fqOpUUMult( + FQATOM * pLValue, + FQATOM * pRValue, + FQATOM * pResult); + +FSTATIC void fqOpUSMult( + FQATOM * pLValue, + FQATOM * pRValue, + FQATOM * pResult); + +FSTATIC void fqOpSSMult( + FQATOM * pLValue, + FQATOM * pRValue, + FQATOM * pResult); + +FSTATIC void fqOpSUMult( + FQATOM * pLValue, + FQATOM * pRValue, + FQATOM * pResult); + +FSTATIC void fqOpUUDiv( + FQATOM * pLValue, + FQATOM * pRValue, + FQATOM * pResult); + +FSTATIC void fqOpUSDiv( + FQATOM * pLValue, + FQATOM * pRValue, + FQATOM * pResult); + +FSTATIC void fqOpSSDiv( + FQATOM * pLValue, + FQATOM * pRValue, + FQATOM * pResult); + +FSTATIC void fqOpSUDiv( + FQATOM * pLValue, + FQATOM * pRValue, + FQATOM * pResult); + +FSTATIC void fqOpUUMod( + FQATOM * pLValue, + FQATOM * pRValue, + FQATOM * pResult); + +FSTATIC void fqOpUSMod( + FQATOM * pLValue, + FQATOM * pRValue, + FQATOM * pResult); + +FSTATIC void fqOpSSMod( + FQATOM * pLValue, + FQATOM * pRValue, + FQATOM * pResult); + +FSTATIC void fqOpSUMod( + FQATOM * pLValue, + FQATOM * pRValue, + FQATOM * pResult); + +FSTATIC void fqOpUUPlus( + FQATOM * pLValue, + FQATOM * pRValue, + FQATOM * pResult); + +FSTATIC void fqOpUSPlus( + FQATOM * pLValue, + FQATOM * pRValue, + FQATOM * pResult); + +FSTATIC void fqOpSSPlus( + FQATOM * pLValue, + FQATOM * pRValue, + FQATOM * pResult); + +FSTATIC void fqOpSUPlus( + FQATOM * pLValue, + FQATOM * pRValue, + FQATOM * pResult); + +FSTATIC void fqOpUUMinus( + FQATOM * pLValue, + FQATOM * pRValue, + FQATOM * pResult); + +FSTATIC void fqOpUSMinus( + FQATOM * pLValue, + FQATOM * pRValue, + FQATOM * pResult); + +FSTATIC void fqOpSSMinus( + FQATOM * pLValue, + FQATOM * pRValue, + FQATOM * pResult); + +FSTATIC void fqOpSUMinus( + FQATOM * pLValue, + FQATOM * pRValue, + FQATOM * pResult); + +FSTATIC RCODE flmCurDoNeg( + FQATOM * pResult); - OpUUBitAND, - OpUUBitAND, - OpSyntaxError, - OpUUBitAND, - OpUUBitAND, - OpSyntaxError, - OpSyntaxError, - OpSyntaxError, - OpSyntaxError, +typedef void FQ_OPERATION( + FQATOM * pLValue, + FQATOM * pRValue, + FQATOM * pResult); - // BITOR - - OpUUBitOR, - OpUUBitOR, - OpSyntaxError, - OpUUBitOR, - OpUUBitOR, - OpSyntaxError, - OpSyntaxError, - OpSyntaxError, - OpSyntaxError, - - // BITXOR - - OpUUBitXOR, - OpUUBitXOR, - OpSyntaxError, - OpUUBitXOR, - OpUUBitXOR, - OpSyntaxError, - OpSyntaxError, - OpSyntaxError, - OpSyntaxError, - - // MULT - - OpUUMult, - OpUSMult, - OpURMult, - OpSUMult, - OpSSMult, - OpSRMult, - OpRUMult, - OpRSMult, - OpRRMult, - - // DIV - - OpUUDiv, - OpUSDiv, - OpURDiv, - OpSUDiv, - OpSSDiv, - OpSRDiv, - OpRUDiv, - OpRSDiv, - OpRRDiv, - - // MOD - - OpUUMod, - OpUSMod, - OpSyntaxError, - OpSUMod, - OpSSMod, - OpSyntaxError, - OpSyntaxError, - OpSyntaxError, - OpSyntaxError, - - // PLUS - - OpUUPlus, - OpUSPlus, - OpURPlus, - OpSUPlus, - OpSSPlus, - OpSRPlus, - OpRUPlus, - OpRSPlus, - OpRRPlus, - - // MINUS - - OpUUMinus, - OpUSMinus, - OpURMinus, - OpSUMinus, - OpSSMinus, - OpSRMinus, - OpRUMinus, - OpRSMinus, - OpRRMinus +FQ_OPERATION * FQ_ArithOpTable[ + ((LAST_ARITH_OP - FIRST_ARITH_OP) + 1) * 4 ] = +{ +/* U = Unsigned S = Signed + U + U U + S + S + U S + S */ +/* BITAND */ fqOpUUBitAND, fqOpUUBitAND, + fqOpUUBitAND, fqOpUUBitAND, +/* BITOR */ fqOpUUBitOR, fqOpUUBitOR, + fqOpUUBitOR, fqOpUUBitOR, +/* BITXOR */ fqOpUUBitXOR, fqOpUUBitXOR, + fqOpUUBitXOR, fqOpUUBitXOR, +/* MULT */ fqOpUUMult, fqOpUSMult, + fqOpSUMult, fqOpSSMult, +/* DIV */ fqOpUUDiv, fqOpUSDiv, + fqOpSUDiv, fqOpSSDiv, +/* MOD */ fqOpUUMod, fqOpUSMod, + fqOpSUMod, fqOpSSMod, +/* PLUS */ fqOpUUPlus, fqOpUSPlus, + fqOpSUPlus, fqOpSSPlus, +/* MINUS */ fqOpUUMinus, fqOpUSMinus, + fqOpSUMinus, fqOpSSMinus }; +/*************************************************************************** +Desc: Determines if number is the native type. +***************************************************************************/ +FINLINE FLMBOOL isNativeNum( + QTYPES eType) +{ + return( eType == FLM_UINT32_VAL || eType == FLM_INT32_VAL + ? TRUE + : FALSE); +} + +/*************************************************************************** +Desc: Returns a 64-bit unsigned integer +***************************************************************************/ +FINLINE FLMUINT64 fqGetUInt64( + FQATOM * pValue) +{ + if (pValue->eType == FLM_UINT32_VAL) + { + return( (FLMUINT64)pValue->val.uiVal); + } + else if( pValue->eType == FLM_UINT64_VAL) + { + return( pValue->val.ui64Val); + } + else if( pValue->eType == FLM_INT64_VAL) + { + if( pValue->val.i64Val >= 0) + { + return( (FLMUINT64)pValue->val.i64Val); + } + } + else if( pValue->eType == FLM_INT32_VAL) + { + if( pValue->val.iVal >= 0) + { + return( (FLMUINT64)pValue->val.iVal); + } + } + + flmAssert( 0); + return( 0); +} + +/*************************************************************************** +Desc: Returns a 64-bit signed integer +***************************************************************************/ +FINLINE FLMINT64 fqGetInt64( + FQATOM * pValue) +{ + if (pValue->eType == FLM_INT32_VAL) + { + return( (FLMINT64)pValue->val.iVal); + } + else if( pValue->eType == FLM_INT64_VAL) + { + return( pValue->val.i64Val); + } + else if( pValue->eType == FLM_UINT32_VAL) + { + return( (FLMINT64)pValue->val.uiVal); + } + else if( pValue->eType == FLM_UINT64_VAL) + { + if( pValue->val.ui64Val <= (FLMUINT64)FLM_MAX_INT64) + { + return( (FLMINT64)pValue->val.ui64Val); + } + } + + flmAssert( 0); + return( 0); +} + +/*************************************************************************** +Desc: Performs the bit and operation +***************************************************************************/ +FSTATIC void fqOpUUBitAND( + FQATOM * pLValue, + FQATOM * pRValue, + FQATOM * pResult) +{ + if (isNativeNum( pLValue->eType) && isNativeNum( pRValue->eType)) + { + pResult->val.uiVal = pLValue->val.uiVal & pRValue->val.uiVal; + pResult->eType = FLM_UINT32_VAL; + } + else + { + pResult->val.ui64Val = + fqGetUInt64( pLValue) & fqGetUInt64( pRValue); + pResult->eType = FLM_UINT64_VAL; + } +} + +/*************************************************************************** +Desc: Performs the bit or operation +***************************************************************************/ +FSTATIC void fqOpUUBitOR( + FQATOM * pLValue, + FQATOM * pRValue, + FQATOM * pResult) +{ + if (isNativeNum( pLValue->eType) && isNativeNum( pRValue->eType)) + { + pResult->val.uiVal = pLValue->val.uiVal | pRValue->val.uiVal; + pResult->eType = FLM_UINT32_VAL; + } + else + { + pResult->val.ui64Val = + fqGetUInt64( pLValue) | fqGetUInt64( pRValue); + pResult->eType = FLM_UINT64_VAL; + } +} + +/*************************************************************************** +Desc: Performs the bit xor operation +***************************************************************************/ +FSTATIC void fqOpUUBitXOR( + FQATOM * pLValue, + FQATOM * pRValue, + FQATOM * pResult) +{ + if (isNativeNum( pLValue->eType) && isNativeNum( pRValue->eType)) + { + pResult->val.uiVal = pLValue->val.uiVal ^ pRValue->val.uiVal; + pResult->eType = FLM_UINT32_VAL; + } + else + { + pResult->val.ui64Val = + fqGetUInt64( pLValue) ^ fqGetUInt64( pRValue); + pResult->eType = FLM_UINT64_VAL; + } +} + +/*************************************************************************** +Desc: Performs the multiply operation +***************************************************************************/ +FSTATIC void fqOpUUMult( + FQATOM * pLValue, + FQATOM * pRValue, + FQATOM * pResult) +{ + if (isNativeNum( pLValue->eType) && isNativeNum( pRValue->eType)) + { + pResult->val.uiVal = pLValue->val.uiVal * pRValue->val.uiVal; + pResult->eType = FLM_UINT32_VAL; + } + else + { + pResult->val.ui64Val = + fqGetUInt64( pLValue) * fqGetUInt64( pRValue); + pResult->eType = FLM_UINT64_VAL; + } +} + +/*************************************************************************** +Desc: Performs the multiply operation +***************************************************************************/ +FSTATIC void fqOpUSMult( + FQATOM * pLValue, + FQATOM * pRValue, + FQATOM * pResult) +{ + if (isNativeNum( pLValue->eType) && isNativeNum( pRValue->eType)) + { + pResult->val.iVal = (FLMINT)pLValue->val.uiVal * pRValue->val.iVal; + pResult->eType = FLM_INT32_VAL; + } + else + { + pResult->val.i64Val = (FLMINT64) + fqGetUInt64( pLValue) * fqGetInt64( pRValue); + pResult->eType = FLM_INT64_VAL; + } +} + +/*************************************************************************** +Desc: Performs the multiply operation +***************************************************************************/ +FSTATIC void fqOpSSMult( + FQATOM * pLValue, + FQATOM * pRValue, + FQATOM * pResult) +{ + if (isNativeNum( pLValue->eType) && isNativeNum( pRValue->eType)) + { + pResult->val.iVal = pLValue->val.iVal * pRValue->val.iVal; + pResult->eType = (pResult->val.iVal < 0) + ? FLM_INT32_VAL + : FLM_UINT32_VAL; + } + else + { + pResult->val.i64Val = (FLMINT64)(fqGetInt64( pLValue) * + fqGetInt64( pRValue)); + + pResult->eType = (pResult->val.i64Val < 0) + ? FLM_INT64_VAL + : FLM_UINT64_VAL; + } +} + +/*************************************************************************** +Desc: Performs the multiply operation +***************************************************************************/ +FSTATIC void fqOpSUMult( + FQATOM * pLValue, + FQATOM * pRValue, + FQATOM * pResult) +{ + if (isNativeNum( pLValue->eType) && isNativeNum( pRValue->eType)) + { + pResult->val.iVal = pLValue->val.iVal * + (FLMINT)pRValue->val.uiVal; + pResult->eType = FLM_INT32_VAL; + } + else + { + pResult->val.i64Val = (FLMINT64) + (fqGetInt64( pLValue) * fqGetUInt64( pRValue)); + pResult->eType = FLM_INT64_VAL; + } +} + +/*************************************************************************** +Desc: Performs the divide operation +***************************************************************************/ +FSTATIC void fqOpUUDiv( + FQATOM * pLValue, + FQATOM * pRValue, + FQATOM * pResult) +{ + if (isNativeNum( pLValue->eType) && isNativeNum( pRValue->eType)) + { + if( pRValue->val.uiVal) + { + pResult->val.uiVal = pLValue->val.uiVal / pRValue->val.uiVal; + pResult->eType = FLM_UINT32_VAL; + } + else + { + pResult->val.uiVal = 0; // Divide by ZERO case. + pResult->eType = NO_TYPE; + } + } + else + { + FLMUINT64 ui64LValue = fqGetUInt64( pLValue); + FLMUINT64 ui64RValue = fqGetUInt64( pRValue); + + if( ui64RValue) + { + pResult->val.ui64Val = ui64LValue / ui64RValue; + pResult->eType = FLM_UINT64_VAL; + } + else + { + pResult->val.uiVal = 0; // Divide by ZERO case. + pResult->eType = NO_TYPE; + } + } +} + +/*************************************************************************** +Desc: Performs the divide operation +***************************************************************************/ +FSTATIC void fqOpUSDiv( + FQATOM * pLValue, + FQATOM * pRValue, + FQATOM * pResult) +{ + if (isNativeNum( pLValue->eType) && isNativeNum( pRValue->eType)) + { + if( pRValue->val.iVal) + { + pResult->val.iVal = pLValue->val.uiVal / pRValue->val.iVal; + pResult->eType = FLM_INT32_VAL; + } + else + { + pResult->val.uiVal = 0; // Divide by ZERO case. + pResult->eType = NO_TYPE; + } + } + else + { + FLMUINT64 ui64LValue = fqGetUInt64( pLValue); + FLMINT64 i64RValue = fqGetInt64( pRValue); + + if( i64RValue) + { + pResult->val.i64Val = ui64LValue / i64RValue; + pResult->eType = FLM_INT64_VAL; + } + else + { + pResult->val.uiVal = 0; // Divide by ZERO case. + pResult->eType = NO_TYPE; + } + } +} + +/*************************************************************************** +Desc: Performs the divide operation +***************************************************************************/ +FSTATIC void fqOpSSDiv( + FQATOM * pLValue, + FQATOM * pRValue, + FQATOM * pResult) +{ + if (isNativeNum( pLValue->eType) && isNativeNum( pRValue->eType)) + { + if( pRValue->val.iVal) + { + pResult->val.iVal = pLValue->val.iVal / pRValue->val.iVal; + pResult->eType = (pResult->val.iVal < 0) + ? FLM_INT32_VAL : FLM_UINT32_VAL; + } + else + { + pResult->val.uiVal = 0; // Divide by ZERO case. + pResult->eType = NO_TYPE; + } + } + else + { + FLMINT64 i64LValue = fqGetInt64( pLValue); + FLMINT64 i64RValue = fqGetInt64( pRValue); + + if( i64RValue) + { + pResult->val.i64Val = i64LValue / i64RValue; + pResult->eType = (pResult->val.i64Val < 0) + ? FLM_INT64_VAL : FLM_UINT64_VAL; + } + else + { + pResult->val.uiVal = 0; // Divide by ZERO case. + pResult->eType = NO_TYPE; + } + } +} + +/*************************************************************************** +Desc: Performs the divide operation +***************************************************************************/ +FSTATIC void fqOpSUDiv( + FQATOM * pLValue, + FQATOM * pRValue, + FQATOM * pResult) +{ + if (isNativeNum( pLValue->eType) && isNativeNum( pRValue->eType)) + { + if( pRValue->val.uiVal) + { + pResult->val.iVal = pLValue->val.iVal / pRValue->val.uiVal; + pResult->eType = FLM_INT32_VAL; + } + else + { + pResult->val.uiVal = 0; // Divide by ZERO case. + pResult->eType = NO_TYPE; + } + } + else + { + FLMINT64 i64LValue = fqGetInt64( pLValue); + FLMUINT64 ui64RValue = fqGetUInt64( pRValue); + + if( ui64RValue) + { + pResult->val.i64Val = i64LValue / ui64RValue; + pResult->eType = FLM_INT64_VAL; + } + else + { + pResult->val.uiVal = 0; // Divide by ZERO case. + pResult->eType = NO_TYPE; + } + } +} + +/*************************************************************************** +Desc: Performs the modulo operation +***************************************************************************/ +FSTATIC void fqOpUUMod( + FQATOM * pLValue, + FQATOM * pRValue, + FQATOM * pResult) +{ + if (isNativeNum( pLValue->eType) && isNativeNum( pRValue->eType)) + { + if( pRValue->val.uiVal) + { + pResult->val.uiVal = pLValue->val.uiVal % pRValue->val.uiVal; + pResult->eType = FLM_UINT32_VAL; + } + else + { + pResult->val.uiVal = 0; // MOD by ZERO case. + pResult->eType = NO_TYPE; + } + } + else + { + FLMUINT64 ui64LValue = fqGetUInt64( pLValue); + FLMUINT64 ui64RValue = fqGetUInt64( pRValue); + + if( ui64RValue) + { + pResult->val.ui64Val = ui64LValue % ui64RValue; + pResult->eType = FLM_UINT64_VAL; + } + else + { + pResult->val.uiVal = 0; // MOD by ZERO case. + pResult->eType = NO_TYPE; + } + } +} + +/*************************************************************************** +Desc: Performs the modulo operation +***************************************************************************/ +FSTATIC void fqOpUSMod( + FQATOM * pLValue, + FQATOM * pRValue, + FQATOM * pResult) +{ + if (isNativeNum( pLValue->eType) && isNativeNum( pRValue->eType)) + { + if( pRValue->val.iVal) + { + pResult->val.iVal = pLValue->val.uiVal % pRValue->val.iVal; + pResult->eType = FLM_INT32_VAL; + } + else + { + pResult->val.uiVal = 0; // MOD by ZERO case. + pResult->eType = NO_TYPE; + } + } + else + { + FLMUINT64 ui64LValue = fqGetUInt64( pLValue); + FLMINT64 i64RValue = fqGetInt64( pRValue); + + if( i64RValue) + { + pResult->val.i64Val = ui64LValue % i64RValue; + pResult->eType = FLM_INT64_VAL; + } + else + { + pResult->val.uiVal = 0; // MOD by ZERO case. + pResult->eType = NO_TYPE; + } + } +} + +/*************************************************************************** +Desc: Performs the modulo operation +***************************************************************************/ +FSTATIC void fqOpSSMod( + FQATOM * pLValue, + FQATOM * pRValue, + FQATOM * pResult) +{ + if (isNativeNum( pLValue->eType) && isNativeNum( pRValue->eType)) + { + if( pRValue->val.iVal) + { + pResult->val.iVal = pLValue->val.iVal % pRValue->val.iVal; + pResult->eType = (pResult->val.iVal < 0) + ? FLM_INT32_VAL : FLM_UINT32_VAL; + } + else + { + pResult->val.uiVal = 0; // MOD by ZERO case. + pResult->eType = NO_TYPE; + } + } + else + { + FLMINT64 i64LValue = fqGetInt64( pLValue); + FLMINT64 i64RValue = fqGetInt64( pRValue); + + if( i64RValue) + { + pResult->val.i64Val = i64LValue % i64RValue; + pResult->eType = (pResult->val.i64Val < 0) + ? FLM_INT64_VAL : FLM_UINT64_VAL; + } + else + { + pResult->val.uiVal = 0; // MOD by ZERO case. + pResult->eType = NO_TYPE; + } + } +} + +/*************************************************************************** +Desc: Performs the modulo operation +***************************************************************************/ +FSTATIC void fqOpSUMod( + FQATOM * pLValue, + FQATOM * pRValue, + FQATOM * pResult) +{ + if (isNativeNum( pLValue->eType) && isNativeNum( pRValue->eType)) + { + if( pRValue->val.uiVal) + { + pResult->val.iVal = pLValue->val.iVal % pRValue->val.uiVal; + pResult->eType = FLM_INT32_VAL; + } + else + { + pResult->val.uiVal = 0; // MOD by ZERO case. + pResult->eType = NO_TYPE; + } + } + else + { + FLMINT64 i64LValue = fqGetInt64( pLValue); + FLMUINT64 ui64RValue = fqGetUInt64( pRValue); + + if( ui64RValue) + { + pResult->val.i64Val = i64LValue % ui64RValue; + pResult->eType = FLM_INT64_VAL; + } + else + { + pResult->val.uiVal = 0; // MOD by ZERO case. + pResult->eType = NO_TYPE; + } + } +} + +/*************************************************************************** +Desc: Performs an addition operation +***************************************************************************/ +FSTATIC void fqOpUUPlus( + FQATOM * pLValue, + FQATOM * pRValue, + FQATOM * pResult) +{ + if (isNativeNum( pLValue->eType) && isNativeNum( pRValue->eType)) + { + pResult->val.uiVal = pLValue->val.uiVal + pRValue->val.uiVal; + pResult->eType = FLM_UINT32_VAL; + } + else + { + pResult->val.ui64Val = + fqGetUInt64( pLValue) + fqGetUInt64( pRValue); + pResult->eType = FLM_UINT64_VAL; + } +} + +/*************************************************************************** +Desc: Performs an addition operation +***************************************************************************/ +FSTATIC void fqOpUSPlus( + FQATOM * pLValue, + FQATOM * pRValue, + FQATOM * pResult) +{ + if (isNativeNum( pLValue->eType) && isNativeNum( pRValue->eType)) + { + if (pRValue->val.iVal < 0) + { + FLMINT iTmpVal = -pRValue->val.iVal; + + if ((FLMUINT)iTmpVal > pLValue->val.uiVal) + { + pResult->val.iVal = -(iTmpVal - (FLMINT)pLValue->val.uiVal); + pResult->eType = FLM_INT32_VAL; + } + else + { + pResult->val.uiVal = pLValue->val.uiVal - (FLMUINT)iTmpVal; + pResult->eType = FLM_UINT32_VAL; + } + } + else + { + pResult->val.uiVal = pLValue->val.uiVal + (FLMUINT)pRValue->val.iVal; + pResult->eType = FLM_UINT32_VAL; + } + } + else + { + FLMUINT64 ui64LValue = fqGetUInt64( pLValue); + FLMINT64 i64RValue = fqGetInt64( pRValue); + + if (i64RValue < 0) + { + i64RValue = -i64RValue; + + if ((FLMUINT64)i64RValue > ui64LValue) + { + pResult->val.i64Val = -(i64RValue - (FLMINT64)ui64LValue); + pResult->eType = FLM_INT64_VAL; + } + else + { + pResult->val.ui64Val = ui64LValue - (FLMUINT64)i64RValue; + pResult->eType = FLM_UINT64_VAL; + } + } + else + { + pResult->val.ui64Val = ui64LValue + (FLMUINT64)i64RValue; + pResult->eType = FLM_UINT64_VAL; + } + } +} + +/*************************************************************************** +Desc: Performs an addition operation +***************************************************************************/ +FSTATIC void fqOpSSPlus( + FQATOM * pLValue, + FQATOM * pRValue, + FQATOM * pResult) +{ + if (isNativeNum( pLValue->eType) && isNativeNum( pRValue->eType)) + { + pResult->val.iVal = pLValue->val.iVal + pRValue->val.iVal; + pResult->eType = (pResult->val.iVal < 0) + ? FLM_INT32_VAL : FLM_UINT32_VAL; + } + else + { + pResult->val.i64Val = + fqGetInt64( pLValue) + fqGetInt64( pRValue); + pResult->eType = (pResult->val.i64Val < 0) + ? FLM_INT64_VAL : FLM_UINT64_VAL; + } +} + +/*************************************************************************** +Desc: Performs an addition operation +***************************************************************************/ +FSTATIC void fqOpSUPlus( + FQATOM * pLValue, + FQATOM * pRValue, + FQATOM * pResult) +{ + if (isNativeNum( pLValue->eType) && isNativeNum( pRValue->eType)) + { + if (pLValue->val.iVal < 0) + { + FLMINT iTmpVal = -pLValue->val.iVal; + + if ((FLMUINT)iTmpVal > pRValue->val.uiVal) + { + pResult->val.iVal = -(iTmpVal - (FLMINT)pRValue->val.uiVal); + pResult->eType = FLM_INT32_VAL; + } + else + { + pResult->val.uiVal = pRValue->val.uiVal - (FLMUINT)iTmpVal; + pResult->eType = FLM_UINT32_VAL; + } + } + else + { + pResult->val.uiVal = (FLMUINT)pLValue->val.iVal + pRValue->val.uiVal; + pResult->eType = FLM_UINT32_VAL; + } + } + else + { + FLMINT64 i64LValue = fqGetInt64( pLValue); + FLMUINT64 ui64RValue = fqGetUInt64( pRValue); + + if (i64LValue < 0) + { + i64LValue = -i64LValue; + + if ((FLMUINT64)i64LValue > ui64RValue) + { + pResult->val.i64Val = -(i64LValue - (FLMINT64)ui64RValue); + pResult->eType = FLM_INT64_VAL; + } + else + { + pResult->val.ui64Val = ui64RValue - (FLMUINT64)i64LValue; + pResult->eType = FLM_UINT64_VAL; + } + } + else + { + pResult->val.ui64Val = (FLMUINT64)i64LValue + ui64RValue; + pResult->eType = FLM_UINT64_VAL; + } + } +} + +/*************************************************************************** +Desc: Performs a subtraction operation +***************************************************************************/ +FSTATIC void fqOpUUMinus( + FQATOM * pLValue, + FQATOM * pRValue, + FQATOM * pResult) +{ + if (isNativeNum( pLValue->eType) && isNativeNum( pRValue->eType)) + { + if( pLValue->val.uiVal >= pRValue->val.uiVal) + { + pResult->val.uiVal = pLValue->val.uiVal - pRValue->val.uiVal; + pResult->eType = FLM_UINT32_VAL; + } + else + { + pResult->val.iVal = -((FLMINT)(pRValue->val.uiVal - pLValue->val.uiVal)); + pResult->eType = FLM_INT32_VAL; + } + } + else + { + FLMUINT64 ui64LValue = fqGetUInt64( pLValue); + FLMUINT64 ui64RValue = fqGetUInt64( pRValue); + + if( ui64LValue >= ui64RValue) + { + pResult->val.ui64Val = ui64LValue - ui64RValue; + pResult->eType = FLM_UINT64_VAL; + } + else + { + pResult->val.i64Val = -((FLMINT64)(ui64RValue - ui64LValue)); + pResult->eType = FLM_INT64_VAL; + } + } +} + +/*************************************************************************** +Desc: Performs a subtraction operation +***************************************************************************/ +FSTATIC void fqOpUSMinus( + FQATOM * pLValue, + FQATOM * pRValue, + FQATOM * pResult) +{ + if (isNativeNum( pLValue->eType) && isNativeNum( pRValue->eType)) + { + if( pRValue->val.iVal < 0) + { + FLMINT iTmpVal = -pRValue->val.iVal; + + pResult->val.uiVal = pLValue->val.uiVal + (FLMUINT)iTmpVal; + pResult->eType = FLM_UINT32_VAL; + } + else if ((FLMUINT)pRValue->val.iVal > pLValue->val.uiVal) + { + pResult->val.iVal = (FLMINT)pLValue->val.uiVal - pRValue->val.iVal; + pResult->eType = FLM_INT32_VAL; + } + else + { + pResult->val.uiVal = pLValue->val.uiVal - (FLMUINT)pRValue->val.iVal; + pResult->eType = FLM_UINT32_VAL; + } + } + else + { + FLMUINT64 ui64LValue = fqGetUInt64( pLValue); + FLMINT64 i64RValue = fqGetInt64( pRValue); + + if( i64RValue < 0) + { + i64RValue = -i64RValue; + + pResult->val.ui64Val = ui64LValue + (FLMUINT64)i64RValue; + pResult->eType = FLM_UINT64_VAL; + } + else if ((FLMUINT64)i64RValue > ui64LValue) + { + pResult->val.i64Val = (FLMINT64)ui64LValue - i64RValue; + pResult->eType = FLM_INT64_VAL; + } + else + { + pResult->val.ui64Val = ui64LValue - (FLMUINT64)i64RValue; + pResult->eType = FLM_UINT64_VAL; + } + } +} + +/*************************************************************************** +Desc: Performs a subtraction operation +***************************************************************************/ +FSTATIC void fqOpSSMinus( + FQATOM * pLValue, + FQATOM * pRValue, + FQATOM * pResult) +{ + if (isNativeNum( pLValue->eType) && isNativeNum( pRValue->eType)) + { + pResult->val.iVal = pLValue->val.iVal - pRValue->val.iVal; + pResult->eType = FLM_INT32_VAL; + } + else + { + pResult->val.i64Val = fqGetInt64( pLValue) - fqGetInt64( pRValue); + pResult->eType = FLM_INT64_VAL; + } +} + +/*************************************************************************** +Desc: Performs a subtraction operation +***************************************************************************/ +FSTATIC void fqOpSUMinus( + FQATOM * pLValue, + FQATOM * pRValue, + FQATOM * pResult) +{ + if (isNativeNum( pLValue->eType) && isNativeNum( pRValue->eType)) + { + pResult->val.iVal = pLValue->val.iVal - (FLMINT)pRValue->val.uiVal; + pResult->eType = FLM_INT32_VAL; + } + else + { + FLMINT64 i64LValue = fqGetInt64( pLValue); + FLMUINT64 ui64RValue = fqGetUInt64( pRValue); + + pResult->val.i64Val = i64LValue - (FLMINT64)ui64RValue; + pResult->eType = FLM_INT64_VAL; + } +} + /**************************************************************************** Desc: Evaluates a list of QATOM elements, and returns a complex boolean based on their contents. @@ -440,6 +1109,16 @@ FSTATIC FLMUINT flmCurEvalTrueFalse( uiTrueFalse |= FLM_FALSE; } break; + case FLM_INT64_VAL: + if (pTmpQAtom->val.i64Val) + { + uiTrueFalse |= FLM_TRUE; + } + else + { + uiTrueFalse |= FLM_FALSE; + } + break; case FLM_UINT32_VAL: if (pTmpQAtom->val.uiVal) { @@ -450,6 +1129,16 @@ FSTATIC FLMUINT flmCurEvalTrueFalse( uiTrueFalse |= FLM_FALSE; } break; + case FLM_UINT64_VAL: + if (pTmpQAtom->val.ui64Val) + { + uiTrueFalse |= FLM_TRUE; + } + else + { + uiTrueFalse |= FLM_FALSE; + } + break; default: goto Exit; } @@ -568,6 +1257,48 @@ RCODE flmCurGetAtomVal( break; } + case FLM_INT64_VAL: + { + if (!pField || pRecord->getDataLength( pField) == 0) + { + // Default value + + pResult->val.i64Val = 0; + } + else if (uiType == FLM_NUMBER_TYPE || uiType == FLM_TEXT_TYPE) + { + if (RC_BAD( rc = pRecord->getINT64( pField, &pResult->val.i64Val))) + { + + // Try to get the number as an unsigned value. For purposes + // of evaluation, the 64-bit value will still be treated as + // signed. In effect, the large positive value is wrapped and + // becomes a negative value. + + if (rc == FERR_CONV_NUM_OVERFLOW) + { + rc = pRecord->getUINT64( pField, &pResult->val.ui64Val); + eFldType = FLM_UINT64_VAL; + } + } + } + else if (uiType == FLM_CONTEXT_TYPE) + { + rc = pRecord->getUINT( pField, &pResult->val.uiVal); + eFldType = FLM_UINT32_VAL; + } + else + { + rc = RC_SET( FERR_CONV_BAD_SRC_TYPE); + } + + if (RC_OK( rc)) + { + pResult->eType = eFldType; + } + break; + } + case FLM_UINT32_VAL: case FLM_REC_PTR_VAL: { @@ -610,6 +1341,48 @@ RCODE flmCurGetAtomVal( break; } + case FLM_UINT64_VAL: + { + if (!pField || pRecord->getDataLength( pField) == 0) + { + // Default value + + pResult->val.ui64Val = 0; + } + else if (uiType == FLM_NUMBER_TYPE || uiType == FLM_TEXT_TYPE) + { + if (RC_BAD( rc = pRecord->getUINT64( pField, &pResult->val.ui64Val))) + { + + // Try to get the number as a signed value. For purposes of + // evaluation, the 64-bit value will still be treated as + // unsigned. In effect, the negative value is wrapped and + // becomes a large positive value. + + if (rc == FERR_CONV_NUM_UNDERFLOW) + { + rc = pRecord->getINT64( pField, &pResult->val.i64Val); + eFldType = FLM_INT64_VAL; + } + } + } + else if (uiType == FLM_CONTEXT_TYPE) + { + rc = pRecord->getUINT( pField, &(pResult->val.uiVal)); + eFldType = FLM_REC_PTR_VAL; + } + else + { + rc = RC_SET( FERR_CONV_BAD_SRC_TYPE); + } + + if (RC_OK( rc)) + { + pResult->eType = eFldType; + } + break; + } + case FLM_BINARY_VAL: { if (pField) @@ -713,6 +1486,16 @@ RCODE flmCurGetAtomVal( { pResult->eType = FLM_INT32_VAL; } + else if (RC_OK( rc = pRecord->getUINT64( pField, + &pResult->val.ui64Val))) + { + pResult->eType = FLM_UINT64_VAL; + } + else if (RC_OK( rc = pRecord->getINT64( pField, + &pResult->val.i64Val))) + { + pResult->eType = FLM_INT64_VAL; + } break; } @@ -1360,21 +2143,50 @@ Get_Operand: } else { - int opPos = (eOp - FIRST_ARITH_OP) * 9; - QTYPES lhType = (QTYPES) (pLhs->eType - FLM_UINT32_VAL); - QTYPES rhType = (QTYPES) (pRhs->eType - FLM_UINT32_VAL); - - if (lhType > 2 || rhType > 2) + FQ_OPERATION * fnOp; + FLMUINT uiOffset = 0; + + if( IS_UNSIGNED( pLhs->eType)) + { + if( IS_UNSIGNED( pRhs->eType)) + { + uiOffset = 0; + } + else if( IS_SIGNED( pRhs->eType)) + { + uiOffset = 1; + } + else + { + rc = RC_SET( FERR_CURSOR_SYNTAX); + goto Exit; + } + } + else if( IS_SIGNED( pLhs->eType)) + { + if( IS_UNSIGNED( pRhs->eType)) + { + uiOffset = 2; + } + else if( IS_SIGNED( pRhs->eType)) + { + uiOffset = 3; + } + else + { + rc = RC_SET( FERR_CURSOR_SYNTAX); + goto Exit; + } + } + else { rc = RC_SET( FERR_CURSOR_SYNTAX); goto Exit; } - opPos += (lhType * 3) + rhType; - - // Call through a table the operation handling routine. - - rc = (FQ_DoOperation[opPos]) (pLhs, pRhs, pTmpQAtom); + fnOp = FQ_ArithOpTable[ ((((FLMUINT)eOp) - + FIRST_ARITH_OP) * 4) + uiOffset]; + fnOp( pLhs, pRhs, pTmpQAtom); } // Doing contextless, do them all - loop through right hand @@ -2689,677 +3501,7 @@ Exit: /**************************************************************************** Desc: ****************************************************************************/ -FSTATIC RCODE OpSyntaxError( - FQATOM * pLhs, - FQATOM * pRhs, - FQATOM * pResult) -{ - F_UNREFERENCED_PARM( pLhs); - F_UNREFERENCED_PARM( pRhs); - F_UNREFERENCED_PARM( pResult); - - return (RC_SET( FERR_CURSOR_SYNTAX)); -} - -/**************************************************************************** -Desc: -****************************************************************************/ -FSTATIC RCODE OpUUBitAND( - FQATOM * pLhs, - FQATOM * pRhs, - FQATOM * pResult) -{ - pResult->val.uiVal = pLhs->val.uiVal & pRhs->val.uiVal; - pResult->eType = FLM_UINT32_VAL; - return (FERR_OK); -} - -/**************************************************************************** -Desc: -****************************************************************************/ -FSTATIC RCODE OpUUBitOR( - FQATOM * pLhs, - FQATOM * pRhs, - FQATOM * pResult) -{ - pResult->val.uiVal = pLhs->val.uiVal | pRhs->val.uiVal; - pResult->eType = FLM_UINT32_VAL; - return (FERR_OK); -} - -/**************************************************************************** -Desc: -****************************************************************************/ -FSTATIC RCODE OpUUBitXOR( - FQATOM * pLhs, - FQATOM * pRhs, - FQATOM * pResult) -{ - pResult->val.uiVal = pLhs->val.uiVal ^ pRhs->val.uiVal; - pResult->eType = FLM_UINT32_VAL; - return (FERR_OK); -} - -/**************************************************************************** -Desc: -****************************************************************************/ -FSTATIC RCODE OpUUMult( - FQATOM * pLhs, - FQATOM * pRhs, - FQATOM * pResult) -{ - pResult->val.uiVal = pLhs->val.uiVal * pRhs->val.uiVal; - pResult->eType = FLM_UINT32_VAL; - return (FERR_OK); -} - -/**************************************************************************** -Desc: -****************************************************************************/ -FSTATIC RCODE OpUSMult( - FQATOM * pLhs, - FQATOM * pRhs, - FQATOM * pResult) -{ - pResult->val.iVal = (FLMINT) pLhs->val.uiVal * pRhs->val.iVal; - pResult->eType = FLM_INT32_VAL; - return (FERR_OK); -} - -/**************************************************************************** -Desc: -****************************************************************************/ -FSTATIC RCODE OpSSMult( - FQATOM * pLhs, - FQATOM * pRhs, - FQATOM * pResult) -{ - pResult->val.iVal = pLhs->val.iVal * pRhs->val.iVal; - pResult->eType = (pResult->val.iVal < 0) ? FLM_INT32_VAL : FLM_UINT32_VAL; - return (FERR_OK); -} - -/**************************************************************************** -Desc: -****************************************************************************/ -FSTATIC RCODE OpSUMult( - FQATOM * pLhs, - FQATOM * pRhs, - FQATOM * pResult) -{ - pResult->val.iVal = pLhs->val.iVal * (FLMINT) pRhs->val.uiVal; - pResult->eType = FLM_INT32_VAL; - return (FERR_OK); -} - -/**************************************************************************** -Desc: -****************************************************************************/ -FSTATIC RCODE OpURMult( - FQATOM * pLhs, - FQATOM * pRhs, - FQATOM * pResult) -{ - return (OpSyntaxError( pLhs, pRhs, pResult)); -} - -/**************************************************************************** -Desc: -****************************************************************************/ -FSTATIC RCODE OpRUMult( - FQATOM * pLhs, - FQATOM * pRhs, - FQATOM * pResult) -{ - return (OpSyntaxError( pLhs, pRhs, pResult)); -} - -/**************************************************************************** -Desc: -****************************************************************************/ -FSTATIC RCODE OpSRMult( - FQATOM * pLhs, - FQATOM * pRhs, - FQATOM * pResult) -{ - return (OpSyntaxError( pLhs, pRhs, pResult)); -} - -/**************************************************************************** -Desc: -****************************************************************************/ -FSTATIC RCODE OpRSMult( - FQATOM * pLhs, - FQATOM * pRhs, - FQATOM * pResult) -{ - return (OpSyntaxError( pLhs, pRhs, pResult)); -} - -/**************************************************************************** -Desc: -****************************************************************************/ -FSTATIC RCODE OpRRMult( - FQATOM * pLhs, - FQATOM * pRhs, - FQATOM * pResult) -{ - return (OpSyntaxError( pLhs, pRhs, pResult)); -} - -/**************************************************************************** -Desc: -****************************************************************************/ -FSTATIC RCODE OpUUDiv( - FQATOM * pLhs, - FQATOM * pRhs, - FQATOM * pResult) -{ - if (pRhs->val.uiVal) - { - pResult->val.uiVal = pLhs->val.uiVal / pRhs->val.uiVal; - pResult->eType = FLM_UINT32_VAL; - } - else - { - // Divide by ZERO case. - - pResult->val.uiVal = 0; - pResult->eType = FLM_UNKNOWN; - } - - return (FERR_OK); -} - -/**************************************************************************** -Desc: -****************************************************************************/ -FSTATIC RCODE OpUSDiv( - FQATOM * pLhs, - FQATOM * pRhs, - FQATOM * pResult) -{ - if (pRhs->val.iVal) - { - pResult->val.iVal = (FLMINT) pLhs->val.uiVal / pRhs->val.iVal; - pResult->eType = FLM_INT32_VAL; - } - else - { - // Divide by ZERO case. - - pResult->val.uiVal = 0; - pResult->eType = FLM_UNKNOWN; - } - - return (FERR_OK); -} - -/**************************************************************************** -Desc: -****************************************************************************/ -FSTATIC RCODE OpSSDiv( - FQATOM * pLhs, - FQATOM * pRhs, - FQATOM * pResult) -{ - if (pRhs->val.iVal) - { - pResult->val.iVal = pLhs->val.iVal / pRhs->val.iVal; - pResult->eType = (pResult->val.iVal < 0) ? FLM_INT32_VAL : FLM_UINT32_VAL; - } - else - { - pResult->val.uiVal = 0; // divide by ZERO case - pResult->eType = FLM_UNKNOWN; - } - - return (FERR_OK); -} - -/**************************************************************************** -Desc: -****************************************************************************/ -FSTATIC RCODE OpSUDiv( - FQATOM * pLhs, - FQATOM * pRhs, - FQATOM * pResult) -{ - if (pRhs->val.uiVal) - { - pResult->val.iVal = pLhs->val.iVal / (FLMINT) pRhs->val.uiVal; - pResult->eType = FLM_INT32_VAL; - } - else // Divide by ZERO case - let's try not to crash. - { - pResult->val.uiVal = 0; - pResult->eType = FLM_UNKNOWN; - } - - return (FERR_OK); -} - -/**************************************************************************** -Desc: -****************************************************************************/ -FSTATIC RCODE OpURDiv( - FQATOM * pLhs, - FQATOM * pRhs, - FQATOM * pResult) -{ - return (OpSyntaxError( pLhs, pRhs, pResult)); -} - -/**************************************************************************** -Desc: -****************************************************************************/ -FSTATIC RCODE OpRUDiv( - FQATOM * pLhs, - FQATOM * pRhs, - FQATOM * pResult) -{ - return (OpSyntaxError( pLhs, pRhs, pResult)); -} - -/**************************************************************************** -Desc: -****************************************************************************/ -FSTATIC RCODE OpSRDiv( - FQATOM * pLhs, - FQATOM * pRhs, - FQATOM * pResult) -{ - return (OpSyntaxError( pLhs, pRhs, pResult)); -} - -/**************************************************************************** -Desc: -****************************************************************************/ -FSTATIC RCODE OpRSDiv( - FQATOM * pLhs, - FQATOM * pRhs, - FQATOM * pResult) -{ - return (OpSyntaxError( pLhs, pRhs, pResult)); -} - -/**************************************************************************** -Desc: -****************************************************************************/ -FSTATIC RCODE OpRRDiv( - FQATOM * pLhs, - FQATOM * pRhs, - FQATOM * pResult) -{ - return (OpSyntaxError( pLhs, pRhs, pResult)); -} - -/**************************************************************************** -Desc: -****************************************************************************/ -FSTATIC RCODE OpUUMod( - FQATOM * pLhs, - FQATOM * pRhs, - FQATOM * pResult) -{ - if (pRhs->val.uiVal != 0) - { - pResult->val.uiVal = pLhs->val.uiVal % pRhs->val.uiVal; - pResult->eType = FLM_UINT32_VAL; - } - else - { - pResult->val.uiVal = 0; // MOD by ZERO case. - pResult->eType = FLM_UNKNOWN; - } - - return (FERR_OK); -} - -/**************************************************************************** -Desc: -****************************************************************************/ -FSTATIC RCODE OpUSMod( - FQATOM * pLhs, - FQATOM * pRhs, - FQATOM * pResult) -{ - if (pRhs->val.iVal != 0) - { - pResult->val.iVal = (FLMINT) pLhs->val.uiVal / pRhs->val.iVal; - pResult->eType = FLM_INT32_VAL; - } - else - { - pResult->val.uiVal = 0; // MOD by ZERO case - pResult->eType = FLM_UNKNOWN; - } - - return (FERR_OK); -} - -/**************************************************************************** -Desc: -****************************************************************************/ -FSTATIC RCODE OpSSMod( - FQATOM * pLhs, - FQATOM * pRhs, - FQATOM * pResult) -{ - if (pRhs->val.iVal != 0) - { - pResult->val.iVal = pLhs->val.iVal % pRhs->val.iVal; - pResult->eType = (pResult->val.iVal < 0) ? FLM_INT32_VAL : FLM_UINT32_VAL; - } - else - { - // MOD by ZERO case - - pResult->val.uiVal = 0; - pResult->eType = FLM_UNKNOWN; - } - - return (FERR_OK); -} - -/**************************************************************************** -Desc: -****************************************************************************/ -FSTATIC RCODE OpSUMod( - FQATOM * pLhs, - FQATOM * pRhs, - FQATOM * pResult) -{ - if (pRhs->val.uiVal != 0) - { - pResult->val.iVal = pLhs->val.iVal % ((FLMINT) pRhs->val.uiVal); - pResult->eType = FLM_INT32_VAL; - } - else - { - // Divide by ZERO case. - - pResult->val.uiVal = 0; - pResult->eType = FLM_UNKNOWN; - } - - return (FERR_OK); -} - -/**************************************************************************** -Desc: -****************************************************************************/ -FSTATIC RCODE OpUUPlus( - FQATOM * pLhs, - FQATOM * pRhs, - FQATOM * pResult) -{ - pResult->val.uiVal = pLhs->val.uiVal + pRhs->val.uiVal; - pResult->eType = FLM_UINT32_VAL; - return (FERR_OK); -} - -/**************************************************************************** -Desc: -****************************************************************************/ -FSTATIC RCODE OpUSPlus( - FQATOM * pLhs, - FQATOM * pRhs, - FQATOM * pResult) -{ - if ((pRhs->val.iVal >= 0) || (pLhs->val.uiVal > MAX_SIGNED_VAL)) - { - pResult->val.uiVal = pLhs->val.uiVal + (FLMUINT) pRhs->val.iVal; - pResult->eType = FLM_UINT32_VAL; - } - else - { - pResult->val.iVal = (FLMINT) pLhs->val.uiVal + pRhs->val.iVal; - pResult->eType = (pResult->val.iVal < 0) ? FLM_INT32_VAL : FLM_UINT32_VAL; - } - - return (FERR_OK); -} - -/**************************************************************************** -Desc: -****************************************************************************/ -FSTATIC RCODE OpSSPlus( - FQATOM * pLhs, - FQATOM * pRhs, - FQATOM * pResult) -{ - pResult->val.iVal = pLhs->val.iVal + pRhs->val.iVal; - pResult->eType = (pResult->val.iVal < 0) ? FLM_INT32_VAL : FLM_UINT32_VAL; - return (FERR_OK); -} - -/**************************************************************************** -Desc: -****************************************************************************/ -FSTATIC RCODE OpSUPlus( - FQATOM * pLhs, - FQATOM * pRhs, - FQATOM * pResult) -{ - if ((pLhs->val.iVal >= 0) || (pRhs->val.uiVal > MAX_SIGNED_VAL)) - { - pResult->val.uiVal = (FLMUINT) pLhs->val.iVal + pRhs->val.uiVal; - pResult->eType = FLM_UINT32_VAL; - } - else - { - pResult->val.iVal = pLhs->val.iVal + (FLMINT) pRhs->val.uiVal; - pResult->eType = (pResult->val.iVal < 0) ? FLM_INT32_VAL : FLM_UINT32_VAL; - } - - return (FERR_OK); -} - -/**************************************************************************** -Desc: -****************************************************************************/ -FSTATIC RCODE OpURPlus( - FQATOM * pLhs, - FQATOM * pRhs, - FQATOM * pResult) -{ - return (OpSyntaxError( pLhs, pRhs, pResult)); -} - -/**************************************************************************** -Desc: -****************************************************************************/ -FSTATIC RCODE OpRUPlus( - FQATOM * pLhs, - FQATOM * pRhs, - FQATOM * pResult) -{ - return (OpSyntaxError( pLhs, pRhs, pResult)); -} - -/**************************************************************************** -Desc: -****************************************************************************/ -FSTATIC RCODE OpSRPlus( - FQATOM * pLhs, - FQATOM * pRhs, - FQATOM * pResult) -{ - return (OpSyntaxError( pLhs, pRhs, pResult)); -} - -/**************************************************************************** -Desc: -****************************************************************************/ -FSTATIC RCODE OpRSPlus( - FQATOM * pLhs, - FQATOM * pRhs, - FQATOM * pResult) -{ - return (OpSyntaxError( pLhs, pRhs, pResult)); -} - -/**************************************************************************** -Desc: -****************************************************************************/ -FSTATIC RCODE OpRRPlus( - FQATOM * pLhs, - FQATOM * pRhs, - FQATOM * pResult) -{ - return (OpSyntaxError( pLhs, pRhs, pResult)); -} - -/**************************************************************************** -Desc: -****************************************************************************/ -FSTATIC RCODE OpUUMinus( - FQATOM * pLhs, - FQATOM * pRhs, - FQATOM * pResult) -{ - if (pLhs->val.uiVal >= pRhs->val.uiVal) - { - pResult->val.uiVal = pLhs->val.uiVal - pRhs->val.uiVal; - pResult->eType = FLM_UINT32_VAL; - } - else - { - pResult->val.iVal = (FLMINT) (pLhs->val.uiVal - pRhs->val.uiVal); - pResult->eType = FLM_INT32_VAL; - } - - return (FERR_OK); -} - -/**************************************************************************** -Desc: -****************************************************************************/ -FSTATIC RCODE OpUSMinus( - FQATOM * pLhs, - FQATOM * pRhs, - FQATOM * pResult) -{ - - if (pRhs->val.iVal < 0) - { - pResult->val.uiVal = pLhs->val.uiVal - pRhs->val.iVal; - pResult->eType = FLM_UINT32_VAL; - } - else - { - pResult->val.iVal = (FLMINT) pLhs->val.uiVal - pRhs->val.iVal; - pResult->eType = (pResult->val.iVal < 0) ? FLM_INT32_VAL : FLM_UINT32_VAL; - } - - return (FERR_OK); -} - -/**************************************************************************** -Desc: -****************************************************************************/ -FSTATIC RCODE OpSSMinus( - FQATOM * pLhs, - FQATOM * pRhs, - FQATOM * pResult) -{ - if ((pLhs->val.iVal > 0) && (pRhs->val.iVal < 0)) - { - pResult->val.uiVal = (FLMUINT) (pLhs->val.iVal - pRhs->val.iVal); - pResult->eType = FLM_UINT32_VAL; - } - else - { - pResult->val.iVal = pLhs->val.iVal - pRhs->val.iVal; - pResult->eType = (pResult->val.iVal < 0) ? FLM_INT32_VAL : FLM_UINT32_VAL; - } - - return (FERR_OK); -} - -/**************************************************************************** -Desc: -****************************************************************************/ -FSTATIC RCODE OpSUMinus( - FQATOM * pLhs, - FQATOM * pRhs, - FQATOM * pResult) -{ - if (pRhs->val.uiVal > MAX_SIGNED_VAL) - { - pResult->val.iVal = (pLhs->val.iVal - MAX_SIGNED_VAL) - - (FLMINT) (pRhs->val.uiVal - MAX_SIGNED_VAL); - pResult->eType = FLM_INT32_VAL; - } - else - { - pResult->val.iVal = pLhs->val.iVal - (FLMINT) pRhs->val.uiVal; - pResult->eType = (pResult->val.iVal < 0) ? FLM_INT32_VAL : FLM_UINT32_VAL; - } - - return (FERR_OK); -} - -/**************************************************************************** -Desc: -****************************************************************************/ -FSTATIC RCODE OpURMinus( - FQATOM * pLhs, - FQATOM * pRhs, - FQATOM * pResult) -{ - return (OpSyntaxError( pLhs, pRhs, pResult)); -} - -/**************************************************************************** -Desc: -****************************************************************************/ -FSTATIC RCODE OpRUMinus( - FQATOM * pLhs, - FQATOM * pRhs, - FQATOM * pResult) -{ - return (OpSyntaxError( pLhs, pRhs, pResult)); -} - -/**************************************************************************** -Desc: -****************************************************************************/ -FSTATIC RCODE OpSRMinus( - FQATOM * pLhs, - FQATOM * pRhs, - FQATOM * pResult) -{ - return (OpSyntaxError( pLhs, pRhs, pResult)); -} - -/**************************************************************************** -Desc: -****************************************************************************/ -FSTATIC RCODE OpRSMinus( - FQATOM * pLhs, - FQATOM * pRhs, - FQATOM * pResult) -{ - return (OpSyntaxError( pLhs, pRhs, pResult)); -} - -/**************************************************************************** -Desc: -****************************************************************************/ -FSTATIC RCODE OpRRMinus( - FQATOM * pLhs, - FQATOM * pRhs, - FQATOM * pResult) -{ - return (OpSyntaxError( pLhs, pRhs, pResult)); -} - -/**************************************************************************** -Desc: -****************************************************************************/ -RCODE flmCurDoNeg( +FSTATIC RCODE flmCurDoNeg( FQATOM * pResult) { RCODE rc = FERR_OK; @@ -3371,19 +3513,41 @@ RCODE flmCurDoNeg( { if (IS_UNSIGNED( pTmpQAtom->eType)) { - if (pTmpQAtom->val.uiVal >= MAX_SIGNED_VAL) + if (isNativeNum( pTmpQAtom->eType)) { - pTmpQAtom->eType = NO_TYPE; + if (pTmpQAtom->val.uiVal >= (FLMUINT)(FLM_MAX_INT32) + 1) + { + pTmpQAtom->eType = NO_TYPE; + } + else + { + pTmpQAtom->val.iVal = -((FLMINT)(pTmpQAtom->val.uiVal)); + pTmpQAtom->eType = FLM_INT32_VAL; + } } else { - pTmpQAtom->val.iVal = -((FLMINT) (pTmpQAtom->val.uiVal)); - pTmpQAtom->eType = FLM_INT32_VAL; + if (pTmpQAtom->val.ui64Val >= (FLMUINT64)(FLM_MAX_INT64) + 1) + { + pTmpQAtom->eType = NO_TYPE; + } + else + { + pTmpQAtom->val.i64Val = -((FLMINT64)(pTmpQAtom->val.ui64Val)); + pTmpQAtom->eType = FLM_INT64_VAL; + } } } else if (IS_SIGNED( pTmpQAtom->eType)) { - pTmpQAtom->val.iVal *= -1; + if (isNativeNum( pTmpQAtom->eType)) + { + pTmpQAtom->val.iVal *= -1; + } + else + { + pTmpQAtom->val.i64Val *= -1; + } } else if (pTmpQAtom->eType != FLM_UNKNOWN) { @@ -3549,6 +3713,13 @@ FLMINT flmCurDoRelationalOp( break; } + case FLM_UINT64_VAL: + { + iCompVal = FQ_COMPARE( (FLMUINT64)(pLhs->val.uiVal), + pRhs->val.ui64Val); + break; + } + case FLM_INT32_VAL: { if (pRhs->val.iVal < 0) @@ -3563,6 +3734,74 @@ FLMINT flmCurDoRelationalOp( break; } + case FLM_INT64_VAL: + { + if (pRhs->val.i64Val < 0) + { + iCompVal = 1; + } + else + { + iCompVal = FQ_COMPARE( (FLMINT64)(pLhs->val.uiVal), + pRhs->val.i64Val); + } + break; + } + + default: + { + flmAssert( 0); + break; + } + + } + break; + } + + case FLM_UINT64_VAL: + { + switch (pRhs->eType) + { + case FLM_UINT32_VAL: + { + iCompVal = FQ_COMPARE( pLhs->val.ui64Val, (FLMUINT64)pRhs->val.uiVal); + break; + } + + case FLM_UINT64_VAL: + { + iCompVal = FQ_COMPARE( pLhs->val.ui64Val, pRhs->val.ui64Val); + break; + } + + case FLM_INT32_VAL: + { + if (pRhs->val.iVal < 0) + { + iCompVal = 1; + } + else + { + iCompVal = FQ_COMPARE( pLhs->val.ui64Val, + (FLMUINT64)(pRhs->val.iVal)); + } + break; + } + + case FLM_INT64_VAL: + { + if (pRhs->val.i64Val < 0) + { + iCompVal = 1; + } + else + { + iCompVal = FQ_COMPARE( pLhs->val.ui64Val, + (FLMUINT64)(pRhs->val.i64Val)); + } + break; + } + default: { flmAssert( 0); @@ -3583,6 +3822,12 @@ FLMINT flmCurDoRelationalOp( break; } + case FLM_INT64_VAL: + { + iCompVal = FQ_COMPARE( (FLMINT64)(pLhs->val.iVal), pRhs->val.i64Val); + break; + } + case FLM_UINT32_VAL: { if (pLhs->val.iVal < 0) @@ -3597,6 +3842,73 @@ FLMINT flmCurDoRelationalOp( break; } + case FLM_UINT64_VAL: + { + if (pLhs->val.iVal < 0) + { + iCompVal = -1; + } + else + { + iCompVal = FQ_COMPARE( (FLMUINT64)(pLhs->val.iVal), + pRhs->val.ui64Val); + } + break; + } + + default: + { + flmAssert( 0); + break; + } + } + break; + } + + case FLM_INT64_VAL: + { + switch (pRhs->eType) + { + case FLM_INT32_VAL: + { + iCompVal = FQ_COMPARE( pLhs->val.i64Val, (FLMINT64)(pRhs->val.iVal)); + break; + } + + case FLM_INT64_VAL: + { + iCompVal = FQ_COMPARE( pLhs->val.i64Val, pRhs->val.i64Val); + break; + } + + case FLM_UINT32_VAL: + { + if (pLhs->val.i64Val < 0) + { + iCompVal = -1; + } + else + { + iCompVal = FQ_COMPARE( pLhs->val.i64Val, + (FLMINT64)(pRhs->val.uiVal)); + } + break; + } + + case FLM_UINT64_VAL: + { + if (pLhs->val.i64Val < 0) + { + iCompVal = -1; + } + else + { + iCompVal = FQ_COMPARE( (FLMUINT64)(pLhs->val.i64Val), + pRhs->val.ui64Val); + } + break; + } + default: { flmAssert( 0); @@ -3608,10 +3920,19 @@ FLMINT flmCurDoRelationalOp( case FLM_REC_PTR_VAL: { - flmAssert( pRhs->eType == FLM_REC_PTR_VAL || - pRhs->eType == FLM_UINT32_VAL); - - iCompVal = FQ_COMPARE( pLhs->val.uiVal, pRhs->val.uiVal); + if (pRhs->eType == FLM_REC_PTR_VAL || + pRhs->eType == FLM_UINT32_VAL) + { + iCompVal = FQ_COMPARE( pLhs->val.uiVal, pRhs->val.uiVal); + } + else if (pRhs->eType == FLM_UINT64_VAL) + { + iCompVal = FQ_COMPARE( (FLMUINT64)(pLhs->val.uiVal), pRhs->val.ui64Val); + } + else + { + flmAssert( 0); + } break; } diff --git a/flaim/src/fqkeys.cpp b/flaim/src/fqkeys.cpp index 1ecc085..1bd894c 100644 --- a/flaim/src/fqkeys.cpp +++ b/flaim/src/fqkeys.cpp @@ -128,16 +128,6 @@ FSTATIC FLMUINT flmCountCharacters( FLMUINT uiMaxToCount, FLMUINT uiIfdFlags); -FSTATIC void flmUintToBCD( - FLMUINT uiValue, - FLMBYTE * pNumberBuf, - FLMUINT * puiValueLen); - -FSTATIC void flmIntToBCD( - FLMINT iValue, - FLMBYTE * pNumberBuf, - FLMUINT * puiValueLen); - /**************************************************************************** Desc: Compares the contents of the key buffers for two cursor positioning keys, returning one of the following values: @@ -1633,7 +1623,7 @@ RCODE flmBuildFromAndUntilKeys( FLMBOOL bDoKeyMatch = FALSE; FLMBOOL bOriginalCharsLost; FLMBOOL bDBCSLanguage; - FLMBYTE pNumberBuf[8]; + FLMBYTE ucNumberBuf [ F_MAX_NUM64_BUF + 1]; FLMUINT uiTempLen; FLMUINT uiMaxKeySize; @@ -2024,11 +2014,33 @@ RCODE flmBuildFromAndUntilKeys( if (IFD_GET_FIELD_TYPE( pIfd) == FLM_NUMBER_TYPE) { - flmIntToBCD( iValue, pNumberBuf, &uiTempLen); + uiTempLen = sizeof( ucNumberBuf); + (void)FlmINT2Storage( iValue, &uiTempLen, ucNumberBuf); } else { - UD2FBA( (FLMUINT32)iValue, pNumberBuf); + UD2FBA( (FLMUINT32)iValue, ucNumberBuf); + uiTempLen = 4; + } + break; + } + + case FLM_INT64_VAL: + { + FLMINT64 i64Value = pCurPred->pVal->val.i64Val; + if (pCurPred->eOperator == FLM_GT_OP) + { + i64Value++; + } + + if (IFD_GET_FIELD_TYPE( pIfd) == FLM_NUMBER_TYPE) + { + uiTempLen = sizeof( ucNumberBuf); + (void)FlmINT64ToStorage( i64Value, &uiTempLen, ucNumberBuf); + } + else + { + UD2FBA( (FLMUINT32)i64Value, ucNumberBuf); uiTempLen = 4; } break; @@ -2045,11 +2057,34 @@ RCODE flmBuildFromAndUntilKeys( if (IFD_GET_FIELD_TYPE( pIfd) == FLM_NUMBER_TYPE) { - flmUintToBCD( uiValue, pNumberBuf, &uiTempLen); + uiTempLen = sizeof( ucNumberBuf); + (void)FlmUINT2Storage( uiValue, &uiTempLen, ucNumberBuf); } else { - UD2FBA( (FLMUINT32)uiValue, pNumberBuf); + UD2FBA( (FLMUINT32)uiValue, ucNumberBuf); + uiTempLen = 4; + } + break; + } + + case FLM_UINT64_VAL: + { + FLMUINT64 ui64Value = pCurPred->pVal->val.ui64Val; + + if (pCurPred->eOperator == FLM_GT_OP) + { + ui64Value++; + } + + if (IFD_GET_FIELD_TYPE( pIfd) == FLM_NUMBER_TYPE) + { + uiTempLen = sizeof( ucNumberBuf); + (void)FlmUINT64ToStorage( ui64Value, &uiTempLen, ucNumberBuf); + } + else + { + UD2FBA( (FLMUINT32)ui64Value, ucNumberBuf); uiTempLen = 4; } break; @@ -2098,7 +2133,7 @@ RCODE flmBuildFromAndUntilKeys( if (RC_BAD( rc = flmAddKeyPiece( uiMaxKeySize, pIfd, FALSE, pFromKey, &uiFromKeyPos, bFromAtFirst, pUntilKey, - &uiUntilKeyPos, bUntilAtEnd, (FLMBYTE*) pNumberBuf, + &uiUntilKeyPos, bUntilAtEnd, ucNumberBuf, uiTempLen, &bDataTruncated, &bDoneBuilding))) { goto Exit; @@ -2966,72 +3001,3 @@ FSTATIC FLMUINT flmCountCharacters( return (uiNumChars); } -/**************************************************************************** -Desc: Cheating routine to blast out an internal number without using the - pool to allocate space. -****************************************************************************/ -FSTATIC void flmUintToBCD( - FLMUINT uiNum, - FLMBYTE * pNumberBuf, - FLMUINT * puiValueLen) -{ - FLMBYTE ucNibStk[ F_MAX_NUM_BUF + 1]; - FLMBYTE * pucNibStk; - - pucNibStk = &ucNibStk[1]; - *pucNibStk++ = 0x0F; - - while (uiNum >= 10) - { - *pucNibStk++ = (FLMBYTE) (uiNum % 10); - uiNum /= 10; - } - - *pucNibStk++ = (FLMBYTE) uiNum; - *puiValueLen = (pucNibStk - ucNibStk) >> 1; - - do - { - *pNumberBuf++ = (FLMBYTE) ((pucNibStk[-1] << 4) | pucNibStk[-2]); - } while ((pucNibStk -= 2) > &ucNibStk[1]); -} - -/**************************************************************************** -Desc: Cheating routine to blast out an internal number without using the - pool to allocate space. Code taken from gnbcd.cpp. -****************************************************************************/ -FSTATIC void flmIntToBCD( - FLMINT iNum, - FLMBYTE * pNumberBuf, - FLMUINT * puiValueLen) -{ - FLMUINT uiNum; - FLMBYTE ucNibStk[F_MAX_NUM_BUF + 1]; - FLMBYTE * pucNibStk; - FLMINT iNegFlag; - - ucNibStk[0] = 0; - ucNibStk[1] = 0x0F; - pucNibStk = &ucNibStk[2]; - uiNum = ((iNegFlag = iNum < 0) != 0) ? -iNum : iNum; - - while (uiNum >= 10) - { - *pucNibStk++ = (FLMBYTE) (uiNum % 10); - uiNum /= 10; - } - - *pucNibStk++ = (FLMBYTE) uiNum; - - if (iNegFlag) - { - *pucNibStk++ = 0x0B; - } - - *puiValueLen = (pucNibStk - ucNibStk) >> 1; - - do - { - *pNumberBuf++ = (FLMBYTE) ((pucNibStk[-1] << 4) | pucNibStk[-2]); - } while ((pucNibStk -= 2) > &ucNibStk[1]); -} diff --git a/flaim/src/fqlog.cpp b/flaim/src/fqlog.cpp index c754d4c..46b8fdf 100644 --- a/flaim/src/fqlog.cpp +++ b/flaim/src/fqlog.cpp @@ -451,10 +451,18 @@ FSTATIC void flmLogPredicate( f_logPrintf( pLogMsg, "%u", (unsigned)pQNode->pQAtom->val.uiVal); break; + case FLM_UINT64_VAL: + f_logPrintf( pLogMsg, "%I64u", + pQNode->pQAtom->val.ui64Val); + break; case FLM_INT32_VAL: f_logPrintf( pLogMsg, "%d", (int)pQNode->pQAtom->val.iVal); break; + case FLM_INT64_VAL: + f_logPrintf( pLogMsg, "%I64d", + pQNode->pQAtom->val.i64Val); + break; case FLM_BINARY_VAL: pLogMsg->appendString( "BINARY("); flmLogBinary( pLogMsg, pQNode->pQAtom->val.pucBuf, diff --git a/flaim/src/fqopt.cpp b/flaim/src/fqopt.cpp index 6537ab8..288a4b7 100644 --- a/flaim/src/fqopt.cpp +++ b/flaim/src/fqopt.cpp @@ -34,9 +34,9 @@ FLMBOOL gv_DoValAndDictTypesMatch[ LAST_VALUE][ FLM_CONTEXT_TYPE + 1] = /*INT32*/ {FALSE, TRUE, FALSE, TRUE}, /*REAL*/ {FALSE, FALSE, FALSE, FALSE}, /*REC_PTR*/ {FALSE, TRUE, FALSE, TRUE}, -/*TIME*/ {FALSE, FALSE, FALSE, FALSE}, -/*DATE*/ {FALSE, FALSE, FALSE, FALSE}, -/*TMSTAMP*/ {FALSE, FALSE, FALSE, FALSE}, +/*UINT64*/ {FALSE, TRUE, FALSE, TRUE}, +/*INT64*/ {FALSE, TRUE, FALSE, TRUE}, +/*NOTUSED*/ {FALSE, FALSE, FALSE, FALSE}, /*BINARY*/ {FALSE, FALSE, TRUE, FALSE}, /*STRING*/ {FALSE, FALSE, FALSE, FALSE}, /*UNICODE*/ {FALSE, FALSE, FALSE, FALSE}, diff --git a/flaim/src/fqparse.cpp b/flaim/src/fqparse.cpp index ea52213..2fbf395 100644 --- a/flaim/src/fqparse.cpp +++ b/flaim/src/fqparse.cpp @@ -39,7 +39,8 @@ FSTATIC RCODE tokenGet( FSTATIC FLMBOOL tokenIsNum( const char * pszToken, - FLMUINT * puiNum); + FLMUINT64 ui64Max, + FLMUINT64 * pui64Num); FSTATIC FLMBOOL tokenIsOperator( const char * pszToken, @@ -326,6 +327,10 @@ FSTATIC RCODE tokenGet( { *peType = FLM_UINT32_VAL; } + else if (f_stricmp( pszTokenStart, "unsigned64") == 0) + { + *peType = FLM_UINT64_VAL; + } else if (f_stricmp( pszTokenStart, "boolean") == 0) { *peType = FLM_BOOL_VAL; @@ -334,6 +339,10 @@ FSTATIC RCODE tokenGet( { *peType = FLM_INT32_VAL; } + else if (f_stricmp( pszTokenStart, "signed64") == 0) + { + *peType = FLM_INT64_VAL; + } else if (f_stricmp( pszTokenStart, "context") == 0) { *peType = FLM_REC_PTR_VAL; @@ -632,7 +641,7 @@ FINLINE QTYPES mapFieldTypeToValType( case FLM_TEXT_TYPE: return( FLM_UNICODE_VAL); case FLM_NUMBER_TYPE: - return( FLM_UINT32_VAL); + return( FLM_UINT64_VAL); case FLM_CONTEXT_TYPE: return( FLM_REC_PTR_VAL); case FLM_BINARY_TYPE: @@ -665,8 +674,9 @@ FSTATIC FLMBOOL tokenIsField( FLMBOOL bIsNum; FLMBOOL bIsDrnNum; FLMBOOL bIsTagNum; + FLMUINT64 ui64Num; FLMUINT uiNum; - FLMUINT uiTagNum; + FLMUINT64 ui64TagNum; FLMUINT uiFieldType; char szNameBuf[ 128]; char * pszNameEnd; @@ -705,7 +715,8 @@ FSTATIC FLMBOOL tokenIsField( bIsTagName = FALSE; } - bIsNum = tokenIsNum( szNameBuf, &uiNum); + bIsNum = tokenIsNum( szNameBuf, (FLMUINT64)(FLM_MAX_UINT16), &ui64Num); + uiNum = (FLMUINT)ui64Num; bIsDrnNum = FALSE; if( f_stricmp( szNameBuf, "DRN") == 0) @@ -715,7 +726,7 @@ FSTATIC FLMBOOL tokenIsField( } bIsTagNum = (f_strnicmp( szNameBuf, "TAG_", 4) == 0 && - tokenIsNum( &szNameBuf[ 4], &uiTagNum)) + tokenIsNum( &szNameBuf[ 4], (FLMUINT64)65535, &ui64TagNum)) ? TRUE : FALSE; @@ -745,7 +756,7 @@ FSTATIC FLMBOOL tokenIsField( } else if( bIsTagNum) { - uiFieldNum = uiTagNum; + uiFieldNum = (FLMUINT)ui64TagNum; } else { @@ -919,7 +930,7 @@ RCODE tokenGetUnicode( char szNumBuf[ 32]; char * pszNumEnd; FLMBOOL bIsNum; - FLMUINT uiNum; + FLMUINT64 ui64Num; // Skip white space and commas @@ -948,11 +959,11 @@ RCODE tokenGetUnicode( break; } - bIsNum = tokenIsNum( szNumBuf, &uiNum); + bIsNum = tokenIsNum( szNumBuf, (FLMUINT64)(FLM_MAX_UINT16), &ui64Num); - if( bIsNum && uiNum && uiNum <= 0xFFFE) + if( bIsNum && ui64Num && ui64Num <= 0xFFFE) { - *puzTmp++ = (FLMUNICODE)uiNum; + *puzTmp++ = (FLMUNICODE)ui64Num; } else { @@ -1106,9 +1117,10 @@ FSTATIC RCODE tokenGetValue( FLMUINT * puiValBufSize) { RCODE rc = FERR_OK; - FLMUINT uiNum; FLMINT32 i32Num; FLMUINT32 ui32Num; + FLMUINT64 ui64Num; + FLMINT64 i64Num; if (bQuoted || eValueType == FLM_UNICODE_VAL) { @@ -1120,42 +1132,145 @@ FSTATIC RCODE tokenGetValue( } } else if (eValueType == FLM_UINT32_VAL || - eValueType == FLM_INT32_VAL) + eValueType == FLM_UINT64_VAL || + eValueType == FLM_INT32_VAL || + eValueType == FLM_INT64_VAL) { - FLMBOOL bNeg = FALSE; - + FLMUINT64 ui64Max; + FLMBOOL bNeg; + if (*pszToken == '-') { bNeg = TRUE; pszToken++; } - if (tokenIsNum( pszToken, &uiNum)) + else { - if (*puiValBufSize < sizeof( FLMINT32)) + bNeg = FALSE; + } + + if (eValueType == FLM_UINT32_VAL) + { + if (bNeg) + { + ui64Max = (FLMUINT64)(FLM_MAX_INT32) + 1; + } + else + { + ui64Max = (FLMUINT64)(FLM_MAX_UINT32); + } + } + else if (eValueType == FLM_INT32_VAL) + { + if (bNeg) + { + ui64Max = (FLMUINT64)(FLM_MAX_INT32) + 1; + } + else + { + ui64Max = (FLMUINT64)(FLM_MAX_INT32); + } + } + else if (eValueType == FLM_UINT64_VAL) + { + if (bNeg) + { + ui64Max = (FLMUINT64)(FLM_MAX_INT64) + 1; + } + else + { + ui64Max = FLM_MAX_UINT64; + } + } + else + { + if (bNeg) + { + ui64Max = (FLMUINT64)(FLM_MAX_INT64) + 1; + } + else + { + ui64Max = (FLMUINT64)(FLM_MAX_INT64); + } + } + if (tokenIsNum( pszToken, ui64Max, &ui64Num)) + { + if (*puiValBufSize < sizeof( FLMUINT64)) { if (RC_BAD( rc = allocValueSpace( ppvVal, puiValBufSize, - sizeof( FLMINT32)))) + sizeof( FLMUINT64)))) { goto Exit; } } - if (bNeg || eValueType == FLM_INT32_VAL) + if (bNeg || eValueType == FLM_INT32_VAL || eValueType == FLM_INT64_VAL) { - i32Num = (FLMINT32)uiNum; - if (bNeg) + if (eValueType == FLM_INT32_VAL || eValueType == FLM_UINT32_VAL) { - i32Num = -i32Num; + if (bNeg) + { + if (ui64Num == ui64Max) + { + + // If the number is negative, the maximum will have been + // set up to be the minimum negative 32 bit integer. + + i32Num = FLM_MIN_INT32; + } + else + { + i32Num = -((FLMINT32)ui64Num); + } + } + else + { + i32Num = (FLMINT32)ui64Num; + } + *peValType = FLM_INT32_VAL; + *((FLMINT32 *)(*ppvVal)) = i32Num; + *puiValLen = sizeof( FLMINT32); + } + else + { + if (bNeg) + { + if (ui64Num == ui64Max) + { + + // If the number is negative, the maximum will have been + // set up to be the minimum negative 64 bit integer. + + i64Num = FLM_MIN_INT64; + } + else + { + i64Num = -((FLMINT64)ui64Num); + } + } + else + { + i64Num = (FLMINT64)ui64Num; + } + *peValType = FLM_INT64_VAL; + *((FLMINT64 *)(*ppvVal)) = i64Num; + *puiValLen = sizeof( FLMINT64); } - *peValType = FLM_INT32_VAL; - *((FLMINT32 *)(*ppvVal)) = i32Num; - *puiValLen = sizeof( FLMINT32); } else { - ui32Num = (FLMUINT32)uiNum; - *peValType = FLM_UINT32_VAL; - *((FLMUINT32 *)(*ppvVal)) = ui32Num; - *puiValLen = sizeof( FLMUINT32); + if (eValueType == FLM_UINT32_VAL) + { + ui32Num = (FLMUINT32)ui64Num; + *peValType = FLM_UINT32_VAL; + *((FLMUINT32 *)(*ppvVal)) = ui32Num; + *puiValLen = sizeof( FLMUINT32); + } + else + { + *peValType = FLM_UINT64_VAL; + *((FLMUINT64 *)(*ppvVal)) = ui64Num; + *puiValLen = sizeof( FLMUINT64); + } } } else @@ -1174,9 +1289,9 @@ FSTATIC RCODE tokenGetValue( goto Exit; } } - if (tokenIsNum( pszToken, &uiNum)) + if (tokenIsNum( pszToken, (FLMUINT64)(FLM_MAX_UINT32), &ui64Num)) { - ui32Num = (FLMUINT32)uiNum; + ui32Num = (FLMUINT32)ui64Num; *peValType = FLM_REC_PTR_VAL; *((FLMUINT32 *)(*ppvVal)) = ui32Num; *puiValLen = sizeof( FLMUINT32); @@ -1197,10 +1312,10 @@ FSTATIC RCODE tokenGetValue( goto Exit; } } - if (tokenIsNum( pszToken, &uiNum)) + if (tokenIsNum( pszToken, FLM_MAX_UINT64, &ui64Num)) { *peValType = FLM_BOOL_VAL; - *((FLMBOOL *)(*ppvVal)) = uiNum ? TRUE : FALSE; + *((FLMBOOL *)(*ppvVal)) = ui64Num ? TRUE : FALSE; *puiValLen = sizeof( FLMBOOL); } else if (f_stricmp( pszToken, "false") == 0) @@ -1247,12 +1362,21 @@ FSTATIC RCODE tokenGetValue( // a number. If that doesn't work, simply // use text. - if (tokenIsNum( pszToken, &uiNum)) + if (tokenIsNum( pszToken, FLM_MAX_UINT64, &ui64Num)) { - ui32Num = (FLMUINT32)uiNum; - *peValType = FLM_UINT32_VAL; - *((FLMUINT32 *)(*ppvVal)) = ui32Num; - *puiValLen = sizeof( FLMUINT32); + if (ui64Num <= (FLMUINT64)(FLM_MAX_UINT32)) + { + ui32Num = (FLMUINT32)ui64Num; + *peValType = FLM_UINT32_VAL; + *((FLMUINT32 *)(*ppvVal)) = ui32Num; + *puiValLen = sizeof( FLMUINT32); + } + else + { + *peValType = FLM_UINT64_VAL; + *((FLMUINT64 *)(*ppvVal)) = ui64Num; + *puiValLen = sizeof( FLMUINT64); + } } else { @@ -1290,7 +1414,7 @@ FLMEXP RCODE FLMAPI FlmParseQuery( char * pszToken = NULL; FLMUINT uiTokenBufSize; FLMBOOL bQuoted; - FLMUINT uiNum; + FLMUINT64 ui64Num; // Allocate space for tokens and values. These will be // reallocated as needed. @@ -1404,7 +1528,7 @@ Add_Field: { goto Add_Field; } - else if (tokenIsNum( pszToken, &uiNum)) + else if (tokenIsNum( pszToken, FLM_MAX_UINT64, &ui64Num)) { goto Get_Value; } @@ -1433,6 +1557,8 @@ Add_Field: case FLM_UNICODE_VAL: case FLM_INT32_VAL: case FLM_UINT32_VAL: + case FLM_UINT64_VAL: + case FLM_INT64_VAL: case FLM_REC_PTR_VAL: case FLM_BINARY_VAL: case FLM_BOOL_VAL: @@ -1472,10 +1598,11 @@ Desc: Determine if a token is a number. ****************************************************************************/ FSTATIC FLMBOOL tokenIsNum( const char * pszToken, - FLMUINT * puiNum) + FLMUINT64 ui64Max, + FLMUINT64 * pui64Num) { FLMBOOL bIsNum = TRUE; - FLMUINT uiNum; + FLMUINT64 ui64Num; FLMBOOL bAllowHex = FALSE; if (*pszToken == 0) @@ -1491,14 +1618,14 @@ FSTATIC FLMBOOL tokenIsNum( bAllowHex = TRUE; } - uiNum = 0; + ui64Num = 0; while (*pszToken) { if (*pszToken >= '0' && *pszToken <= '9') { if (!bAllowHex) { - if (uiNum > (FLMUINT)(-1) / 10) + if (ui64Num > ui64Max / 10) { // Number would overflow. @@ -1508,12 +1635,12 @@ FSTATIC FLMBOOL tokenIsNum( } else { - uiNum *= 10; + ui64Num *= 10; } } else { - if (uiNum > (FLMUINT)(-1) >> 4) + if (ui64Num > ui64Max >> 4) { // Number would overflow. @@ -1521,13 +1648,21 @@ FSTATIC FLMBOOL tokenIsNum( bIsNum = FALSE; goto Exit; } - uiNum <<= 4; + ui64Num <<= 4; } - uiNum += (FLMUINT)(*pszToken - '0'); + if (ui64Num > ui64Max - (FLMUINT64)(*pszToken - '0')) + { + + // Number would overflow. + + bIsNum = FALSE; + goto Exit; + } + ui64Num += (FLMUINT64)(*pszToken - '0'); } else if (bAllowHex) { - if (uiNum > (FLMUINT)(-1) >> 4) + if (ui64Num > ui64Max >> 4) { // Number would overflow. @@ -1537,13 +1672,29 @@ FSTATIC FLMBOOL tokenIsNum( } if (*pszToken >= 'A' && *pszToken <= 'F') { - uiNum <<= 4; - uiNum += (FLMUINT)(*pszToken - 'A') + 10; + ui64Num <<= 4; + if (ui64Num > ui64Max - (FLMUINT64)(*pszToken - 'A' + 10)) + { + + // Number would overflow. + + bIsNum = FALSE; + goto Exit; + } + ui64Num += (FLMUINT)(*pszToken - 'A') + 10; } else if (*pszToken >= 'a' && *pszToken <= 'f') { - uiNum <<= 4; - uiNum += (FLMUINT)(*pszToken - 'a') + 10; + ui64Num <<= 4; + if (ui64Num > ui64Max - (FLMUINT64)(*pszToken - 'a' + 10)) + { + + // Number would overflow. + + bIsNum = FALSE; + goto Exit; + } + ui64Num += (FLMUINT)(*pszToken - 'a') + 10; } else { @@ -1559,9 +1710,10 @@ FSTATIC FLMBOOL tokenIsNum( pszToken++; } - *puiNum = uiNum; + *pui64Num = ui64Num; Exit: return( bIsNum); } + diff --git a/flaim/src/fqprep.cpp b/flaim/src/fqprep.cpp index 8764547..80a53e4 100644 --- a/flaim/src/fqprep.cpp +++ b/flaim/src/fqprep.cpp @@ -640,6 +640,12 @@ RCODE flmCurCopyQNode( break; } + case FLM_INT64_VAL: + { + pVal = (void *)&pSrcNode->pQAtom->val.i64Val; + break; + } + case FLM_REC_PTR_VAL: case FLM_UINT32_VAL: { @@ -647,6 +653,12 @@ RCODE flmCurCopyQNode( break; } + case FLM_UINT64_VAL: + { + pVal = (void *)&pSrcNode->pQAtom->val.ui64Val; + break; + } + case FLM_FLD_PATH: { // Count the number of fields in the field path. diff --git a/flaim/src/fqstack.cpp b/flaim/src/fqstack.cpp index a794fd4..5bc1ae6 100644 --- a/flaim/src/fqstack.cpp +++ b/flaim/src/fqstack.cpp @@ -521,9 +521,15 @@ RCODE flmPutValInAtom( case FLM_REC_PTR_VAL: pQAtom->val.uiVal = *((FLMUINT *)pvVal); break; + case FLM_UINT64_VAL: + pQAtom->val.ui64Val = *((FLMUINT64 *)pvVal); + break; case FLM_INT32_VAL: pQAtom->val.iVal = *((FLMINT *)pvVal); break; + case FLM_INT64_VAL: + pQAtom->val.i64Val = *((FLMINT64 *)pvVal); + break; case FLM_BINARY_VAL: case FLM_TEXT_VAL: pQAtom->val.pucBuf = (FLMBYTE *)pvVal; @@ -614,6 +620,12 @@ RCODE flmCurMakeQNode( break; } + case FLM_INT64_VAL: + { + pQAtom->val.i64Val = *(FLMINT64 *)pVal; + break; + } + case FLM_REC_PTR_VAL: case FLM_UINT32_VAL: { @@ -621,6 +633,12 @@ RCODE flmCurMakeQNode( break; } + case FLM_UINT64_VAL: + { + pQAtom->val.ui64Val = *(FLMUINT64 *)pVal; + break; + } + case FLM_FLD_PATH: { for (uiPathCnt = 0; @@ -839,13 +857,14 @@ FLMEXP RCODE FLMAPI FlmCursorAddValue( pTmpVal = &uiVal; break; + case FLM_UINT64_VAL: + case FLM_INT64_VAL: case FLM_TEXT_VAL: - pTmpVal = pVal; - eValType = FLM_TEXT_VAL; - break; - case FLM_BINARY_VAL: - eValType = FLM_BINARY_VAL; + + // pTmpVal is already pointing to pVal, and + // eValType does not need to be changed. + break; default: diff --git a/flaim/src/fquery.h b/flaim/src/fquery.h index 0400a53..021e69b 100644 --- a/flaim/src/fquery.h +++ b/flaim/src/fquery.h @@ -95,12 +95,6 @@ Desc: Macros used for determining the nature and precedence of OP codes. #define IS_BUF_TYPE( e) ((e) == FLM_TEXT_VAL || \ (e) == FLM_BINARY_VAL) -#define IS_UNSIGNED( e) ((e) == FLM_UINT32_VAL) - -#define IS_SIGNED( e) ((e) == FLM_INT32_VAL) - -#define IS_REAL( e) ((e) == FLM_REAL_VAL) - #define DO_REVERSE( e) (((e) == FLM_GT_OP) ? FLM_LT_OP : \ ((e) == FLM_LT_OP) ? FLM_GT_OP : \ ((e) == FLM_GE_OP) ? FLM_LE_OP : \ @@ -156,6 +150,8 @@ typedef struct FQATOM FLMUINT uiBool; FLMUINT uiVal; FLMINT iVal; + FLMUINT64 ui64Val; + FLMINT64 i64Val; F_TIME Time; F_DATE Date; F_TMSTAMP TimeStamp; @@ -385,11 +381,6 @@ typedef struct CURSOR FLMUINT uiCursorId; } CURSOR; -typedef RCODE FQ_OPERATION( - FQATOM * lhs, // Left hand side - FQATOM * rhs, // Right hand side - FQATOM * pResult); // Newly allocated result side - RCODE flmCurDbInit( CURSOR * pCursor); @@ -457,9 +448,6 @@ RCODE flmCurEvalCompareOp( FLMBOOL bHaveKey, FQATOM * pResult); -RCODE flmCurDoNeg( - FQATOM * pResult); - FLMUINT flmCurDoMatchOp( FQATOM * lhs, FQATOM * rhs, @@ -477,9 +465,6 @@ FLMUINT flmCurDoContainsOp( FQATOM * rhs, FLMUINT uiLang); -RCODE flmCurDoNeg( - FQATOM * pResult); - FLMINT flmTextCompare( FLMBYTE * pLeftBuf, FLMUINT uiLeftLen, diff --git a/flaim/src/frebuild.cpp b/flaim/src/frebuild.cpp index b31de79..4738989 100644 --- a/flaim/src/frebuild.cpp +++ b/flaim/src/frebuild.cpp @@ -1413,7 +1413,7 @@ FSTATIC RCODE bldGetOneRec( { if (!pStateInfo->uiEncId) { - eCorruptionCode = flmVerifyField( pValue, + eCorruptionCode = flmVerifyField( pStateInfo, pValue, pStateInfo->uiFieldLen, pStateInfo->uiFieldType); } @@ -1431,7 +1431,7 @@ FSTATIC RCODE bldGetOneRec( { goto Exit; } - eCorruptionCode = flmVerifyField( pData, + eCorruptionCode = flmVerifyField( pStateInfo, pData, pStateInfo->uiFieldLen, pStateInfo->uiFieldType); } diff --git a/flaim/src/frec.cpp b/flaim/src/frec.cpp index 43604ef..d0f45ce 100644 --- a/flaim/src/frec.cpp +++ b/flaim/src/frec.cpp @@ -387,6 +387,67 @@ Exit: return( rc); } +/***************************************************************************** +Desc: +*****************************************************************************/ +RCODE FlmRecord::setINT64( + void * pvField, + FLMINT64 i64Number, + FLMUINT uiEncId) +{ + RCODE rc = FERR_OK; + FLMBYTE * pucData; + FLMBYTE ucStorageBuf[ F_MAX_NUM64_BUF + 1]; + FLMUINT uiStorageLen; + FLMUINT uiEncDataLen = 0; + FLMUINT uiEncFlags = 0; + + if( isReadOnly() || isCached()) + { + flmAssert( 0); + rc = RC_SET( FERR_FAILURE); + goto Exit; + } + + uiStorageLen = sizeof( ucStorageBuf); + + if( RC_BAD( rc = FlmINT64ToStorage( i64Number, &uiStorageLen, ucStorageBuf))) + { + goto Exit; + } + + if( uiEncId) + { + // For encrypted fields, we want to make sure we allocate + // enough space for the encrypted data too. The data does + // not get encrypted until the call to FlmRecordModify or + // FlmRecordAdd. + + if( uiStorageLen % 16) + { + uiEncDataLen = uiStorageLen + (16 - (uiStorageLen % 16)); + } + else + { + uiEncDataLen = uiStorageLen; + } + + uiEncFlags = FLD_HAVE_DECRYPTED_DATA; + } + + if( RC_BAD( rc = getNewDataPtr( getFieldPointer( pvField), FLM_NUMBER_TYPE, + uiStorageLen, uiEncDataLen, uiEncId, uiEncFlags, &pucData, NULL))) + { + goto Exit; + } + + f_memcpy( pucData, ucStorageBuf, uiStorageLen); + +Exit: + + return( rc); +} + /***************************************************************************** Desc: *****************************************************************************/ @@ -447,6 +508,66 @@ Exit: return( rc); } +/***************************************************************************** +Desc: +*****************************************************************************/ +RCODE FlmRecord::setUINT64( + void * pvField, + FLMUINT64 ui64Number, + FLMUINT uiEncId) +{ + RCODE rc = FERR_OK; + FLMBYTE * pucData; + FLMBYTE ucStorageBuf[ F_MAX_NUM64_BUF + 1]; + FLMUINT uiStorageLen; + FLMUINT uiEncDataLen = 0; + FLMUINT uiEncFlags = 0; + + if( isReadOnly() || isCached()) + { + flmAssert( 0); + rc = RC_SET( FERR_FAILURE); + goto Exit; + } + + uiStorageLen = sizeof( ucStorageBuf); + if( RC_BAD( rc = FlmUINT64ToStorage( ui64Number, &uiStorageLen, ucStorageBuf))) + { + goto Exit; + } + + if( uiEncId) + { + // For encrypted fields, we want to make sure we allocate + // enough space for the encrypted data too. The data does + // not get encrypted until the call to FlmRecordModify or + // FlmRecordAdd. + + if( uiStorageLen % 16) + { + uiEncDataLen = uiStorageLen + (16 - (uiStorageLen % 16)); + } + else + { + uiEncDataLen = uiStorageLen; + } + + uiEncFlags = FLD_HAVE_DECRYPTED_DATA; + } + + if( RC_BAD( rc = getNewDataPtr( getFieldPointer( pvField), FLM_NUMBER_TYPE, + uiStorageLen, uiEncDataLen, uiEncId, uiEncFlags, &pucData, NULL))) + { + goto Exit; + } + + f_memcpy( pucData, ucStorageBuf, uiStorageLen); + +Exit: + + return( rc); +} + /***************************************************************************** Desc: *****************************************************************************/ @@ -4257,6 +4378,96 @@ Exit: } +/***************************************************************************** +Desc: +*****************************************************************************/ +RCODE FlmRecord::getINT32( + void * pvField, + FLMINT32 * pi32Number) +{ + RCODE rc = FERR_OK; + FLMBOOL bEncrypted; + FlmField * pField = getFieldPointer( pvField); + + if (!pField) + { + rc = RC_SET( FERR_NOT_FOUND); + goto Exit; + } + + bEncrypted = isEncryptedField( pField); + + if (!bEncrypted || + (getEncFlags( pField) & FLD_HAVE_DECRYPTED_DATA)) + { + rc = FlmStorage2INT32( getFieldDataType( pField), + getFieldDataLength( pField), + (const FLMBYTE *)getDataPtr( pField), + pi32Number); + } + else if (bEncrypted && + !(getEncFlags( pField) & FLD_HAVE_DECRYPTED_DATA)) + { + rc = RC_SET( FERR_ENCRYPTION_UNAVAILABLE); + goto Exit; + } + else + { + rc = RC_SET( FERR_NOT_FOUND); + goto Exit; + } + +Exit: + + return( rc); + +} + +/***************************************************************************** +Desc: +*****************************************************************************/ +RCODE FlmRecord::getINT64( + void * pvField, + FLMINT64 * pi64Number) +{ + RCODE rc = FERR_OK; + FLMBOOL bEncrypted; + FlmField * pField = getFieldPointer( pvField); + + if (!pField) + { + rc = RC_SET( FERR_NOT_FOUND); + goto Exit; + } + + bEncrypted = isEncryptedField( pField); + + if (!bEncrypted || + (getEncFlags( pField) & FLD_HAVE_DECRYPTED_DATA)) + { + rc = FlmStorage2INT64( getFieldDataType( pField), + getFieldDataLength( pField), + (const FLMBYTE *)getDataPtr( pField), + pi64Number); + } + else if (bEncrypted && + !(getEncFlags( pField) & FLD_HAVE_DECRYPTED_DATA)) + { + rc = RC_SET( FERR_ENCRYPTION_UNAVAILABLE); + goto Exit; + } + else + { + rc = RC_SET( FERR_NOT_FOUND); + goto Exit; + } + +Exit: + + return( rc); + +} + /***************************************************************************** Desc: *****************************************************************************/ @@ -4348,6 +4559,52 @@ Exit: } +/***************************************************************************** +Desc: +*****************************************************************************/ +RCODE FlmRecord::getUINT64( + void * pvField, + FLMUINT64 * pui64Number) +{ + RCODE rc = FERR_OK; + FLMBOOL bEncrypted; + FlmField * pField = getFieldPointer( pvField); + + if (!pField) + { + rc = RC_SET( FERR_NOT_FOUND); + goto Exit; + } + + bEncrypted = isEncryptedField( pField); + + if (!bEncrypted || + (getEncFlags( pField) & FLD_HAVE_DECRYPTED_DATA)) + { + rc = FlmStorage2UINT64( getFieldDataType( pField), + getFieldDataLength( pField), + (const FLMBYTE *)getDataPtr( pField), + pui64Number); + } + else if (bEncrypted && + !(getEncFlags( pField) & FLD_HAVE_DECRYPTED_DATA)) + { + rc = RC_SET( FERR_ENCRYPTION_UNAVAILABLE); + goto Exit; + } + else + { + rc = RC_SET( FERR_NOT_FOUND); + goto Exit; + } + +Exit: + + return( rc); + +} + + /***************************************************************************** Desc: *****************************************************************************/ @@ -5686,11 +5943,11 @@ void * RecCursor::Scan( void * pvIDMatch = NULL; FLMUINT uiTargetLevel = pTargetCursor->Level(); FLMBOOL bAdvanced = FALSE; + RecCursor candidate = this; *peMatchType = GRD_NoMatch; - for (RecCursor candidate = this; - candidate.Level() >= uiTargetLevel && !candidate.EndOfRecord(); + for ( ; candidate.Level() >= uiTargetLevel && !candidate.EndOfRecord(); candidate.Advance(), bAdvanced = TRUE) { if (pTargetCursor->FieldIdIsEqualTo( &candidate)) @@ -5896,22 +6153,28 @@ RCODE flmAddField( { case 0: uiNum = (FLMUINT)(*((FLMUINT *)(pvData))); + rc = pRecord->setUINT( pvField, uiNum); break; case 1: uiNum = (FLMUINT)(*((FLMBYTE *)(pvData))); + rc = pRecord->setUINT( pvField, uiNum); break; case 2: uiNum = (FLMUINT)(*((FLMUINT16 *)(pvData))); + rc = pRecord->setUINT( pvField, uiNum); break; case 4: uiNum = (FLMUINT)(*((FLMUINT32 *)(pvData))); + rc = pRecord->setUINT( pvField, uiNum); + break; + case 8: + rc = pRecord->setUINT64( pvField, *((FLMUINT64 *)(pvData))); break; default: flmAssert( 0); rc = RC_SET( FERR_INVALID_PARM); goto Exit; } - rc = pRecord->setUINT( pvField, uiNum); break; } case FLM_BINARY_TYPE: @@ -5970,22 +6233,28 @@ RCODE flmModField( { case 0: uiNum = (FLMUINT)(*((FLMUINT *)(pvData))); + rc = pRecord->setUINT( pvField, uiNum); + break; case 1: uiNum = (FLMUINT)(*((FLMBYTE *)(pvData))); + rc = pRecord->setUINT( pvField, uiNum); break; case 2: uiNum = (FLMUINT)(*((FLMUINT16 *)(pvData))); + rc = pRecord->setUINT( pvField, uiNum); break; case 4: uiNum = (FLMUINT)(*((FLMUINT32 *)(pvData))); + rc = pRecord->setUINT( pvField, uiNum); + break; + case 8: + rc = pRecord->setUINT64( pvField, *((FLMUINT64 *)(pvData))); break; default: flmAssert( 0); rc = RC_SET( FERR_INVALID_PARM); goto Exit; } - - rc = pRecord->setUINT( pvField, uiNum); break; } @@ -6105,3 +6374,4 @@ RCODE flmDecrField( return( rc); } + diff --git a/flaim/src/fsrecupd.cpp b/flaim/src/fsrecupd.cpp index b05ebbc..abef0fb 100644 --- a/flaim/src/fsrecupd.cpp +++ b/flaim/src/fsrecupd.cpp @@ -306,7 +306,7 @@ FSTATIC RCODE FSBldRecElement( { if( uiFldType == FLM_NUMBER_TYPE) { - if( uiValueLen > 6) + if( uiValueLen > 11) { flmAssert( 0); rc = RC_SET( FERR_BAD_DATA_LENGTH); diff --git a/flaim/src/fstructs.h b/flaim/src/fstructs.h index 84ea34d..29e44f8 100644 --- a/flaim/src/fstructs.h +++ b/flaim/src/fstructs.h @@ -1679,18 +1679,6 @@ typedef struct FBak FLMBYTE ucDbPath[ F_PATH_MAX_SIZE]; } FBak; -/**************************************************************************** -Desc: -****************************************************************************/ -typedef struct BCD_TYPE -{ - const FLMBYTE * pucPtr; - FLMUINT uiNibCnt; - FLMUINT uiNum; - FLMBOOL bNegFlag; - FLMBYTE ucNumBuf[ F_MAX_NUM_BUF]; -} BCD_TYPE; - /**************************************************************************** Desc: ****************************************************************************/ diff --git a/flaim/src/fsv.cpp b/flaim/src/fsv.cpp index d70122c..088f785 100644 --- a/flaim/src/fsv.cpp +++ b/flaim/src/fsv.cpp @@ -2683,7 +2683,7 @@ FSTATIC RCODE fsvIteratorWhereParse( if (bNegative) { - FLMINT32 i32Value; + FLMINT64 i64Value; if (uiTag == FCS_ITERATOR_REC_PTR_VALUE) { @@ -2691,38 +2691,38 @@ FSTATIC RCODE fsvIteratorWhereParse( goto Exit; } - if (RC_BAD( rc = GedGetINT32( pCurNode, &i32Value))) + if (RC_BAD( rc = GedGetINT64( pCurNode, &i64Value))) { goto Exit; } - if (RC_BAD( rc = FlmCursorAddValue( hIterator, FLM_INT32_VAL, - &i32Value, 0))) + if (RC_BAD( rc = FlmCursorAddValue( hIterator, FLM_INT64_VAL, + &i64Value, 0))) { goto Exit; } } else { - FLMUINT32 ui32Value; + FLMUINT64 ui64Value; FLMUINT uiValue; - if (RC_BAD( rc = GedGetUINT32( pCurNode, &ui32Value))) + if (RC_BAD( rc = GedGetUINT64( pCurNode, &ui64Value))) { goto Exit; } if (uiTag == FCS_ITERATOR_NUMBER_VALUE) { - if (RC_BAD( rc = FlmCursorAddValue( hIterator, FLM_UINT32_VAL, - &ui32Value, 0))) + if (RC_BAD( rc = FlmCursorAddValue( hIterator, FLM_UINT64_VAL, + &ui64Value, 0))) { goto Exit; } } else if (uiTag == FCS_ITERATOR_REC_PTR_VALUE) { - uiValue = ui32Value; + uiValue = (FLMUINT)ui64Value; if (RC_BAD( rc = FlmCursorAddValue( hIterator, FLM_REC_PTR_VAL, &uiValue, 0))) { diff --git a/flaim/src/imonqury.cpp b/flaim/src/imonqury.cpp index 120539d..09700c2 100644 --- a/flaim/src/imonqury.cpp +++ b/flaim/src/imonqury.cpp @@ -952,10 +952,18 @@ void F_QueryFormatter::outputPredicate( f_sprintf( szBuf, "%u", (unsigned)pQNode->pQAtom->val.uiVal); appendString( szBuf, Q_VALUE_COLOR); break; + case FLM_UINT64_VAL: + f_sprintf( szBuf, "%I64u", pQNode->pQAtom->val.ui64Val); + appendString( szBuf, Q_VALUE_COLOR); + break; case FLM_INT32_VAL: f_sprintf( szBuf, "%d", (int)pQNode->pQAtom->val.iVal); appendString( szBuf, Q_VALUE_COLOR); break; + case FLM_INT64_VAL: + f_sprintf( szBuf, "%I64d", pQNode->pQAtom->val.i64Val); + appendString( szBuf, Q_VALUE_COLOR); + break; case FLM_BINARY_VAL: appendString( "BINARY", Q_LABEL_COLOR); outputBinary( pQNode->pQAtom->val.pucBuf, diff --git a/flaim/src/kybuild.cpp b/flaim/src/kybuild.cpp index 87ae910..61abe03 100644 --- a/flaim/src/kybuild.cpp +++ b/flaim/src/kybuild.cpp @@ -24,6 +24,23 @@ #include "flaimsys.h" +// Constants for checking to see if numbers are greater than what will fit +// in 32 bits. the B at the beginning signifies a negative value + +static const FLMBYTE gv_ucMinInt32 [6] = +{ + 0xB2,0x14,0x74,0x83,0x64,0x8F +}; + +// Note that the last byte is 0xFF, but it could be 0xF1, 0xF2, etc - it really +// doesn't matter what is in the lower nibble, because the number terminates +// when it sees the F in the high nibble. + +static const FLMBYTE gv_ucMaxUInt32 [6] = +{ + 0x42,0x94,0x96,0x72,0x95,0xFF +}; + #define KREF_TBL_SIZE 512 #define KREF_TBL_THRESHOLD 400 #define KREF_POOL_BLOCK_SIZE 8192 @@ -83,6 +100,7 @@ RCODE flmProcessRecFlds( void * pathFlds[GED_MAXLVLNUM + 1]; FLMUINT uiLeafFieldLevel; void * pvField; + FLMUINT uiDbVersion = pDb->pFile->FileHdr.uiVersionNum; if ((pvField = pRecord->root()) == NULL) { @@ -100,6 +118,7 @@ RCODE flmProcessRecFlds( FLMUINT uiEncFlags = 0; FLMUINT uiEncId = 0; FLMUINT uiEncState; + FLMUINT uiFieldType = pRecord->getDataType( pvField); if (RC_BAD( rc = fdictGetField( pDb->pDict, uiTagNum, &uiItemType, &pIfdChain, &uiFldState))) @@ -109,7 +128,7 @@ RCODE flmProcessRecFlds( pDb->Diag.uiInfoFlags |= (FLM_DIAG_FIELD_NUM | FLM_DIAG_FIELD_TYPE); pDb->Diag.uiFieldNum = uiTagNum; - pDb->Diag.uiFieldType = (FLMUINT) pRecord->getDataType( pvField); + pDb->Diag.uiFieldType = uiFieldType; goto Exit; } @@ -206,24 +225,109 @@ RCODE flmProcessRecFlds( } } - if (uiItemType != pRecord->getDataType( pvField) && - uiTagNum < FLM_DICT_FIELD_NUMS) + if (uiItemType != uiFieldType && uiTagNum < FLM_DICT_FIELD_NUMS) { rc = RC_SET( FERR_BAD_FIELD_TYPE); pDb->Diag.uiInfoFlags |= (FLM_DIAG_FIELD_NUM | FLM_DIAG_FIELD_TYPE); pDb->Diag.uiFieldNum = uiTagNum; - pDb->Diag.uiFieldType = (FLMUINT) pRecord->getDataType( pvField); + pDb->Diag.uiFieldType = uiFieldType; goto Exit; } - if (pRecord->getDataType( pvField) == FLM_BLOB_TYPE && - (!(uiAction & KREF_INDEXING_ONLY))) + if (uiFieldType == FLM_BLOB_TYPE) { - if (RC_BAD( rc = flmBlobPlaceInTransactionList( pDb, - ((uiAction & KREF_DEL_KEYS) ? BLOB_DELETE_ACTION : BLOB_ADD_ACTION), - pRecord, pvField))) + if (!(uiAction & KREF_INDEXING_ONLY)) { - goto Exit; + if (RC_BAD( rc = flmBlobPlaceInTransactionList( pDb, + ((uiAction & KREF_DEL_KEYS) ? BLOB_DELETE_ACTION : BLOB_ADD_ACTION), + pRecord, pvField))) + { + goto Exit; + } + } + } + else if (uiFieldType == FLM_NUMBER_TYPE) + { + + // Make sure if the database version is not at least 4.62 that we + // don't allow numbers that are too large into the database. + + if (uiDbVersion < FLM_FILE_FORMAT_VER_4_62) + { + const FLMBYTE * pucDataPtr; + FLMUINT uiDataLength = pRecord->getDataLength( pvField); + + // All data lengths less than six will be ok. All data lengths + // greater than six will be bad. + + if (uiDataLength < 6) + { + // For numbers whose data length is less than six, the number + // is guaranteed to fit in 32 bits. + } + else if (uiDataLength > 6) + { + + // Any numbers whose data length is greater than six are more + // than 32 bits. + + rc = RC_SET( FERR_64BIT_NUMS_NOT_SUPPORTED); + goto Exit; + } + else // uiDataLength == 6 + { + + // Check for encryption - make sure we have the decrypted data to + // look at. + + if (pRecord->isEncryptedField( pvField) && + !(pRecord->getEncFlags( pvField) & FLD_HAVE_DECRYPTED_DATA)) + { + rc = RC_SET( FERR_ENCRYPTION_UNAVAILABLE); + goto Exit; + } + pucDataPtr = pRecord->getDataPtr( pvField); + + // See if the number is negative. + + if ((*pucDataPtr & 0xF0) == 0xB0) + { + // The sixth byte should have an F in either the upper or + // lower nibble. If it is in the upper nibble, the number + // will fit in 32 bits. + + if ((pucDataPtr [5] & 0xF0) == 0xF0) + { + // F was in upper nibble, number will fit in 32 bits. + } + else + { + // The sixth byte should have an F in the lower nibble, so + // it is ok to compare all six bytes. We are looking for + // something greater than B2,14,74,83,64,8F + + if (f_memcmp( pucDataPtr, gv_ucMinInt32, 6) > 0) + { + rc = RC_SET( FERR_64BIT_NUMS_NOT_SUPPORTED); + goto Exit; + } + } + } + else + { + // If the sixth byte is not an F in the high nibble, we + // have more than a 32 bit value. If it has an F in the + // high nibble, check the first five bytes to make sure + // they are not greater than 42,94,96,72,95 + + if ((pucDataPtr [5] & 0xF0) != 0xF0 || + f_memcmp( pucDataPtr, gv_ucMaxUInt32, 5) > 0) + { + rc = RC_SET( FERR_64BIT_NUMS_NOT_SUPPORTED); + goto Exit; + } + } + } } } diff --git a/flaim/src/scache.cpp b/flaim/src/scache.cpp index ada2b1c..2eb77c5 100644 --- a/flaim/src/scache.cpp +++ b/flaim/src/scache.cpp @@ -3821,7 +3821,7 @@ FSTATIC RCODE ScaBlkSanityCheck( { if (StateInfo.uiFOPType != FLM_FOP_REC_INFO) { - if (flmVerifyField( StateInfo.pFOPData, + if (flmVerifyField( &StateInfo, StateInfo.pFOPData, StateInfo.uiFOPDataLen, StateInfo.uiFieldType) != FLM_NO_CORRUPTION) { diff --git a/flaim/util/basic_test.cpp b/flaim/util/basic_test.cpp index 09a66c6..f11fa43 100644 --- a/flaim/util/basic_test.cpp +++ b/flaim/util/basic_test.cpp @@ -35,12 +35,19 @@ FSTATIC const char * gv_pszSampleDictionary = " 1 type number\n" "0 @5@ field Misc\n" " 1 type binary\n" + "0 @6@ field Numbers\n" + " 1 type number\n" "0 @100@ index LastFirst_IX\n" " 1 language US\n" " 1 key\n" " 2 field 2\n" " 3 required\n" " 2 field 3\n" + " 3 required\n" + "0 @101@ index NUMBER_IX\n" + " 1 language US\n" + " 1 key\n" + " 2 field 6\n" " 3 required\n"; #define PERSON_TAG 1 @@ -48,7 +55,9 @@ FSTATIC const char * gv_pszSampleDictionary = #define FIRST_NAME_TAG 3 #define AGE_TAG 4 #define MISC_TAG 5 +#define NUMBER_TAG 6 #define LAST_NAME_FIRST_NAME_IX 100 +#define NUMBER_IX 101 #ifdef FLM_NLM #define DB_NAME_STR "SYS:\\SAMPLE.DB" @@ -66,6 +75,167 @@ FSTATIC const char * gv_pszSampleDictionary = #define BACKUP_PATH "samplebackup" #endif +typedef struct NUM_IX_VALUE +{ + FLMBOOL bUnsigned; + FLMUINT64 ui64Value; + FLMINT64 i64Value; +} NUM_IX_VALUE; + +#define NUM_NUM_KEYS 17 +static NUM_IX_VALUE gv_ExpectedNumIxValues [NUM_NUM_KEYS] = +{ + {FALSE, 0, (FLMINT64)FLM_MIN_INT64}, + {FALSE, 0, (FLMINT64)FLM_MIN_INT64 + 1}, + {FALSE, 0, (FLMINT64)(FLM_MIN_INT32) - 1}, + {FALSE, 0, (FLMINT64)(FLM_MIN_INT32)}, + {FALSE, 0, (FLMINT64)(FLM_MIN_INT32) + 1}, + {FALSE, 0, (FLMINT64)(-1)}, + {TRUE, 0, 0}, + {TRUE, (FLMUINT64)FLM_MAX_INT32 - 1, 0}, + {TRUE, (FLMUINT64)FLM_MAX_INT32, 0}, + {TRUE, (FLMUINT64)FLM_MAX_INT32 + 1, 0}, + {TRUE, (FLMUINT64)FLM_MAX_UINT32, 0}, + {TRUE, (FLMUINT64)FLM_MAX_UINT32 + 1, 0}, + {TRUE, (FLMUINT64)FLM_MAX_INT64 - 1, 0}, + {TRUE, (FLMUINT64)FLM_MAX_INT64, 0}, + {TRUE, (FLMUINT64)FLM_MAX_INT64 + 1, 0}, + {TRUE, (FLMUINT64)FLM_MAX_UINT64 - 1, 0}, + {TRUE, (FLMUINT64)FLM_MAX_UINT64, 0} +}; + +typedef struct FLMUINT_TEST +{ + FLMUINT uiNum; + RCODE rcExpectedGetUINT; + RCODE rcExpectedGetINT; + RCODE rcExpectedGetUINT64; + RCODE rcExpectedGetINT64; +} FLMUINT_TEST; + +typedef struct FLMUINT64_TEST +{ + FLMUINT64 ui64Num; + RCODE rcExpectedGetUINT; + RCODE rcExpectedGetINT; + RCODE rcExpectedGetUINT64; + RCODE rcExpectedGetINT64; +} UNSIGNED63_TEST; + +typedef struct FLMINT_TEST +{ + FLMINT iNum; + RCODE rcExpectedGetUINT; + RCODE rcExpectedGetINT; + RCODE rcExpectedGetUINT64; + RCODE rcExpectedGetINT64; +} FLMINT_TEST; + +typedef struct FLMINT64_TEST +{ + FLMINT64 i64Num; + RCODE rcExpectedGetUINT; + RCODE rcExpectedGetINT; + RCODE rcExpectedGetUINT64; + RCODE rcExpectedGetINT64; +} FLMINT64_TEST; + +/*************************************************************************** +Desc: FLMUINT numbers to test +****************************************************************************/ +#define NUM_FLMUINT_TESTS 3 +static FLMUINT_TEST gv_FLMUINTTests [NUM_FLMUINT_TESTS] = +{ + // Number GetFLMUINT RCODE GetFLMINT RCODE GetFLMUINT64 RCODE GetFLMINT64 RCODE + {0, FERR_OK, FERR_OK, FERR_OK, FERR_OK}, +#ifdef FLM64_BIT + {FLM_MAX_UINT, FERR_OK, FERR_CONV_NUM_OVERFLOW, FERR_OK, FERR_CONV_NUM_OVERFLOW}, + ((FLMUINT)(FLM_MAX_UINT32), FERR_OK, FERR_OK, FERR_OK, FERR_OK}, +#else + {FLM_MAX_UINT, FERR_OK, FERR_CONV_NUM_OVERFLOW, FERR_OK, FERR_OK}, + {(FLMUINT)(FLM_MAX_UINT32), FERR_OK, FERR_CONV_NUM_OVERFLOW, FERR_OK, FERR_OK} +#endif +}; + +/*************************************************************************** +Desc: FLMINT numbers to test +****************************************************************************/ +#define NUM_FLMINT_TESTS 7 +static FLMINT_TEST gv_FLMINTTests [NUM_FLMINT_TESTS] = +{ + // Number GetFLMUINT RCODE GetFLMINT RCODE GetFLMUINT64 RCODE GetFLMINT64 RCODE + {-1, FERR_CONV_NUM_UNDERFLOW, FERR_OK, FERR_CONV_NUM_UNDERFLOW, FERR_OK}, + {FLM_MIN_INT, FERR_CONV_NUM_UNDERFLOW, FERR_OK, FERR_CONV_NUM_UNDERFLOW, FERR_OK}, + {FLM_MAX_INT, FERR_OK, FERR_OK, FERR_OK, FERR_OK}, + {(FLMINT)FLM_MIN_INT32, FERR_CONV_NUM_UNDERFLOW, FERR_OK, FERR_CONV_NUM_UNDERFLOW, FERR_OK}, + {(FLMINT)(FLM_MIN_INT32) + 1, FERR_CONV_NUM_UNDERFLOW, FERR_OK, FERR_CONV_NUM_UNDERFLOW, FERR_OK}, + {(FLMINT)(FLM_MAX_INT32), FERR_OK, FERR_OK, FERR_OK, FERR_OK}, + {(FLMINT)(FLM_MAX_INT32) - 1, FERR_OK, FERR_OK, FERR_OK, FERR_OK} +}; + +/*************************************************************************** +Desc: FLMUINT64 numbers to test +****************************************************************************/ +#ifndef FLM64_BIT + #define NUM_FLMUINT64_TESTS 8 +#else + #define NUM_FLMUINT64_TESTS 7 +#endif +static FLMUINT64_TEST gv_FLMUINT64Tests [NUM_FLMUINT64_TESTS] = +{ + // Number GetFLMUINT RCODE GetFLMINT RCODE GetFLMUINT64 RCODE GetFLMINT64 RCODE + {0, FERR_OK, FERR_OK, FERR_OK, FERR_OK}, +#ifndef FLM64_BIT + {(FLMUINT64)(FLM_MAX_UINT) + 1, FERR_CONV_NUM_OVERFLOW, FERR_CONV_NUM_OVERFLOW, FERR_OK, FERR_OK}, +#endif + {(FLMUINT64)(FLM_MAX_UINT32) + 1,FERR_CONV_NUM_OVERFLOW, FERR_CONV_NUM_OVERFLOW, FERR_OK, FERR_OK}, +#ifdef FLM64_BIT + {(FLMUINT64)(FLM_MAX_INT64) - 1, FERR_OK, FERR_OK, FERR_OK, FERR_OK}, + {(FLMUINT64)(FLM_MAX_INT64), FERR_OK, FERR_OK, FERR_OK, FERR_OK}, + {(FLMUINT64)(FLM_MAX_INT64) + 1, FERR_OK, FERR_CONV_NUM_OVERFLOW, FERR_OK, FERR_CONV_NUM_OVERFLOW}, + {FLM_MAX_UINT64 - 1, FERR_OK, FERR_CONV_NUM_OVERFLOW, FERR_OK, FERR_CONV_NUM_OVERFLOW}, + {FLM_MAX_UINT64, FERR_OK, FERR_CONV_NUM_OVERFLOW, FERR_OK, FERR_CONV_NUM_OVERFLOW}, +#else + {(FLMUINT64)(FLM_MAX_INT64) - 1, FERR_CONV_NUM_OVERFLOW, FERR_CONV_NUM_OVERFLOW, FERR_OK, FERR_OK}, + {(FLMUINT64)(FLM_MAX_INT64), FERR_CONV_NUM_OVERFLOW, FERR_CONV_NUM_OVERFLOW, FERR_OK, FERR_OK}, + {(FLMUINT64)(FLM_MAX_INT64) + 1, FERR_CONV_NUM_OVERFLOW, FERR_CONV_NUM_OVERFLOW, FERR_OK, FERR_CONV_NUM_OVERFLOW}, + {FLM_MAX_UINT64 - 1, FERR_CONV_NUM_OVERFLOW, FERR_CONV_NUM_OVERFLOW, FERR_OK, FERR_CONV_NUM_OVERFLOW}, + {FLM_MAX_UINT64, FERR_CONV_NUM_OVERFLOW, FERR_CONV_NUM_OVERFLOW, FERR_OK, FERR_CONV_NUM_OVERFLOW} +#endif +}; + +/*************************************************************************** +Desc: FLMINT64 numbers to test +****************************************************************************/ +#ifndef FLM64_BIT + #define NUM_FLMINT64_TESTS 9 +#else + #define NUM_FLMINT64_TESTS 7 +#endif +static FLMINT64_TEST gv_FLMINT64Tests [NUM_FLMINT64_TESTS] = +{ + // Number GetFLMUINT RCODE GetFLMINT RCODE GetFLMUINT64 RCODE GetFLMINT64 RCODE + {-1, FERR_CONV_NUM_UNDERFLOW, FERR_OK, FERR_CONV_NUM_UNDERFLOW, FERR_OK}, +#ifndef FLM64_BIT + {(FLMINT64)(FLM_MIN_INT) - 1, FERR_CONV_NUM_UNDERFLOW, FERR_CONV_NUM_UNDERFLOW,FERR_CONV_NUM_UNDERFLOW, FERR_OK}, + {(FLMINT64)(FLM_MAX_INT) + 1, FERR_OK, FERR_CONV_NUM_OVERFLOW, FERR_OK, FERR_OK}, +#endif + {(FLMINT64)(FLM_MIN_INT32) - 1, FERR_CONV_NUM_UNDERFLOW, FERR_CONV_NUM_UNDERFLOW,FERR_CONV_NUM_UNDERFLOW, FERR_OK}, +#ifdef FLM64_BIT + {(FLMINT64)(FLM_MAX_INT32) + 1, FERR_OK, FERR_OK, FERR_OK, FERR_OK}, + {FLM_MIN_INT64, FERR_CONV_NUM_UNDERFLOW, FERR_OK, FERR_CONV_NUM_UNDERFLOW, FERR_OK}, + {FLM_MIN_INT64 + 1, FERR_CONV_NUM_UNDERFLOW, FERR_OK, FERR_CONV_NUM_UNDERFLOW, FERR_OK}, + {FLM_MAX_INT64 - 1, FERR_OK, FERR_OK, FERR_OK, FERR_OK}, + {FLM_MAX_INT64, FERR_CONV_NUM_UNDERFLOW, FERR_OK, FERR_CONV_NUM_UNDERFLOW, FERR_OK}, +#else + {(FLMINT64)(FLM_MAX_INT32) + 1, FERR_OK, FERR_CONV_NUM_OVERFLOW, FERR_OK, FERR_OK}, + {FLM_MIN_INT64, FERR_CONV_NUM_UNDERFLOW, FERR_CONV_NUM_UNDERFLOW,FERR_CONV_NUM_UNDERFLOW, FERR_OK}, + {FLM_MIN_INT64 + 1, FERR_CONV_NUM_UNDERFLOW, FERR_CONV_NUM_UNDERFLOW,FERR_CONV_NUM_UNDERFLOW, FERR_OK}, + {FLM_MAX_INT64 - 1, FERR_CONV_NUM_OVERFLOW, FERR_CONV_NUM_OVERFLOW, FERR_OK, FERR_OK}, + {FLM_MAX_INT64, FERR_CONV_NUM_OVERFLOW, FERR_CONV_NUM_OVERFLOW, FERR_OK, FERR_OK} +#endif +}; + /*************************************************************************** Desc: ****************************************************************************/ @@ -138,6 +308,43 @@ public: FLMUINT uiDrn, FLMBOOL bDoRootedFieldPaths); + RCODE addRecWithFLMUINT( + FLMUINT uiNum, + FLMUINT * puiDrn); + + RCODE addRecWithFLMUINT64( + FLMUINT64 ui64Num, + FLMUINT * puiDrn); + + RCODE addRecWithFLMINT( + FLMINT iNum, + FLMUINT * puiDrn); + + RCODE addRecWithFLMINT64( + FLMINT64 i64Num, + FLMUINT * puiDrn); + + RCODE numbersTest( + FLMUINT * puiDrn); + + RCODE reopenDbTest( void); + + RCODE testNumField( + FLMUINT * puiDrn, + FLMUINT uiExpectedNum, + RCODE rcExpectedUINT, + FLMINT iExpectedNum, + RCODE rcExpectedINT, + FLMUINT64 ui64ExpectedNum, + RCODE rcExpectedUINT64, + FLMINT64 i64ExpectedNum, + RCODE rcExpectedINT64); + + RCODE numbersRetrieveTest( + FLMUINT uiDrn); + + RCODE numbersKeyRetrieveTest( void); + RCODE backupRestoreDbTest( void); RCODE compareRecords( @@ -2743,6 +2950,875 @@ Exit: return( rc); } +/*************************************************************************** +Desc: +****************************************************************************/ +RCODE IFlmTestImpl::addRecWithFLMUINT( + FLMUINT uiNum, + FLMUINT * puiDrn) +{ + RCODE rc = FERR_OK; + char szErr [100]; + void * pvDataField; + FLMUINT uiTestNum; + FlmRecord * pDataRec = NULL; + FLMUINT uiDrn; + + // Create a person object + + if( (pDataRec = f_new FlmRecord) == NULL) + { + rc = RC_SET( FERR_MEM); + MAKE_ERROR_STRING( "allocating FlmRecord", rc, m_szFailInfo); + goto Exit; + } + if( RC_BAD( rc = pDataRec->insertLast( 0, PERSON_TAG, + FLM_TEXT_TYPE, &pvDataField))) + { + MAKE_ERROR_STRING( "calling insertLast", rc, m_szFailInfo); + goto Exit; + } + + if( RC_BAD( rc = pDataRec->insertLast( 1, NUMBER_TAG, + FLM_NUMBER_TYPE, &pvDataField))) + { + f_sprintf( szErr, "calling insertLast to add Unsigned %u", + (unsigned)uiNum); + MAKE_ERROR_STRING( szErr, rc, m_szFailInfo); + goto Exit; + } + if (RC_BAD( rc = pDataRec->setUINT( pvDataField, uiNum))) + { + f_sprintf( szErr, "calling setUINT to add Unsigned %u", + (unsigned)uiNum); + MAKE_ERROR_STRING( szErr, rc, m_szFailInfo); + goto Exit; + } + + // Verify that we get back the expected data. + // Set the test number to a different value than the passed in value to + // ensure that we are actually changing it in the get call. + + uiTestNum = uiNum + 1; + if (RC_BAD( rc = pDataRec->getUINT( pvDataField, &uiTestNum))) + { + f_sprintf( szErr, "calling getUINT for Unsigned value %u", + (unsigned)uiNum); + MAKE_ERROR_STRING( szErr, rc, m_szFailInfo); + goto Exit; + } + if (uiTestNum != uiNum) + { + rc = RC_SET( FERR_FAILURE); + f_sprintf( m_szFailInfo, + "Unsigned value set not retrieved, Set: %u, Retrieved: %u", + (unsigned)uiNum, (unsigned)uiTestNum); + goto Exit; + } + + uiDrn = 0; + if( RC_BAD( rc = FlmRecordAdd( m_hDb, FLM_DATA_CONTAINER, + &uiDrn, pDataRec, 0))) + { + MAKE_ERROR_STRING( "calling FlmRecordAdd", rc, m_szFailInfo); + goto Exit; + } + if (puiDrn) + { + *puiDrn = uiDrn; + } + +Exit: + + if (pDataRec) + { + pDataRec->Release(); + } + + return( rc); +} + +/*************************************************************************** +Desc: +****************************************************************************/ +RCODE IFlmTestImpl::addRecWithFLMUINT64( + FLMUINT64 ui64Num, + FLMUINT * puiDrn) +{ + RCODE rc = FERR_OK; + char szErr [100]; + void * pvDataField; + FLMUINT64 ui64TestNum; + FlmRecord * pDataRec = NULL; + FLMUINT uiDrn; + + // Create a person object + + if( (pDataRec = f_new FlmRecord) == NULL) + { + rc = RC_SET( FERR_MEM); + MAKE_ERROR_STRING( "allocating FlmRecord", rc, m_szFailInfo); + goto Exit; + } + if( RC_BAD( rc = pDataRec->insertLast( 0, PERSON_TAG, + FLM_TEXT_TYPE, &pvDataField))) + { + MAKE_ERROR_STRING( "calling insertLast", rc, m_szFailInfo); + goto Exit; + } + + if( RC_BAD( rc = pDataRec->insertLast( 1, NUMBER_TAG, + FLM_NUMBER_TYPE, &pvDataField))) + { + f_sprintf( szErr, "calling insertLast to add Unsigned64 %I64u", ui64Num); + MAKE_ERROR_STRING( szErr, rc, m_szFailInfo); + goto Exit; + } + if (RC_BAD( rc = pDataRec->setUINT64( pvDataField, ui64Num))) + { + f_sprintf( szErr, "calling setUINT64 to add Unsigned64 %I64u", ui64Num); + MAKE_ERROR_STRING( szErr, rc, m_szFailInfo); + goto Exit; + } + + // Verify that we get back the expected data. + // Set the test number to a different value than the passed in value to + // ensure that we are actually changing it in the get call. + + ui64TestNum = ui64Num + 1; + if (RC_BAD( rc = pDataRec->getUINT64( pvDataField, &ui64TestNum))) + { + f_sprintf( szErr, "calling getUINT64 for Unsigned64 value %I64u", ui64Num); + MAKE_ERROR_STRING( szErr, rc, m_szFailInfo); + goto Exit; + } + if (ui64TestNum != ui64Num) + { + rc = RC_SET( FERR_FAILURE); + f_sprintf( m_szFailInfo, + "Unsigned64 value set not retrieved, Set: %I64u, Retrieved: %I64u", + ui64Num, ui64TestNum); + goto Exit; + } + + uiDrn = 0; + if( RC_BAD( rc = FlmRecordAdd( m_hDb, FLM_DATA_CONTAINER, + &uiDrn, pDataRec, 0))) + { + MAKE_ERROR_STRING( "calling FlmRecordAdd", rc, m_szFailInfo); + goto Exit; + } + if (puiDrn) + { + *puiDrn = uiDrn; + } + +Exit: + + if (pDataRec) + { + pDataRec->Release(); + } + + return( rc); +} + +/*************************************************************************** +Desc: +****************************************************************************/ +RCODE IFlmTestImpl::addRecWithFLMINT( + FLMINT iNum, + FLMUINT * puiDrn) +{ + RCODE rc = FERR_OK; + char szErr [100]; + void * pvDataField; + FLMINT iTestNum; + FlmRecord * pDataRec = NULL; + FLMUINT uiDrn; + + // Create a person object + + if( (pDataRec = f_new FlmRecord) == NULL) + { + rc = RC_SET( FERR_MEM); + MAKE_ERROR_STRING( "allocating FlmRecord", rc, m_szFailInfo); + goto Exit; + } + if( RC_BAD( rc = pDataRec->insertLast( 0, PERSON_TAG, + FLM_TEXT_TYPE, &pvDataField))) + { + MAKE_ERROR_STRING( "calling insertLast", rc, m_szFailInfo); + goto Exit; + } + + if( RC_BAD( rc = pDataRec->insertLast( 1, NUMBER_TAG, + FLM_NUMBER_TYPE, &pvDataField))) + { + f_sprintf( szErr, "calling insertLast to add Signed %d", (int)iNum); + MAKE_ERROR_STRING( szErr, rc, m_szFailInfo); + goto Exit; + } + if (RC_BAD( rc = pDataRec->setINT( pvDataField, iNum))) + { + f_sprintf( szErr, "calling setINT to add Signed %d", (int)iNum); + MAKE_ERROR_STRING( szErr, rc, m_szFailInfo); + goto Exit; + } + + // Verify that we get back the expected data. + // Set the test number to a different value than the passed in value to + // ensure that we are actually changing it in the get call. + + iTestNum = iNum + 1; + if (RC_BAD( rc = pDataRec->getINT( pvDataField, &iTestNum))) + { + f_sprintf( szErr, "calling getINT for Signed value %d", (int)iNum); + MAKE_ERROR_STRING( szErr, rc, m_szFailInfo); + goto Exit; + } + if (iTestNum != iNum) + { + rc = RC_SET( FERR_FAILURE); + f_sprintf( m_szFailInfo, + "Signed value set not retrieved, Set: %d, Retrieved: %d", + (int)iNum, (int)iTestNum); + goto Exit; + } + + uiDrn = 0; + if( RC_BAD( rc = FlmRecordAdd( m_hDb, FLM_DATA_CONTAINER, + &uiDrn, pDataRec, 0))) + { + MAKE_ERROR_STRING( "calling FlmRecordAdd", rc, m_szFailInfo); + goto Exit; + } + if (puiDrn) + { + *puiDrn = uiDrn; + } + +Exit: + + if (pDataRec) + { + pDataRec->Release(); + } + + return( rc); +} + +/*************************************************************************** +Desc: +****************************************************************************/ +RCODE IFlmTestImpl::addRecWithFLMINT64( + FLMINT64 i64Num, + FLMUINT * puiDrn) +{ + RCODE rc = FERR_OK; + char szErr [100]; + void * pvDataField; + FLMINT64 i64TestNum; + FlmRecord * pDataRec = NULL; + FLMUINT uiDrn; + + // Create a person object + + if( (pDataRec = f_new FlmRecord) == NULL) + { + rc = RC_SET( FERR_MEM); + MAKE_ERROR_STRING( "allocating FlmRecord", rc, m_szFailInfo); + goto Exit; + } + if( RC_BAD( rc = pDataRec->insertLast( 0, PERSON_TAG, + FLM_TEXT_TYPE, &pvDataField))) + { + MAKE_ERROR_STRING( "calling insertLast", rc, m_szFailInfo); + goto Exit; + } + + if( RC_BAD( rc = pDataRec->insertLast( 1, NUMBER_TAG, + FLM_NUMBER_TYPE, &pvDataField))) + { + f_sprintf( szErr, "calling insertLast to add Signed64 %I64d", i64Num); + MAKE_ERROR_STRING( szErr, rc, m_szFailInfo); + goto Exit; + } + if (RC_BAD( rc = pDataRec->setINT64( pvDataField, i64Num))) + { + f_sprintf( szErr, "calling setINT64 to add Signed64 %I64d", i64Num); + MAKE_ERROR_STRING( szErr, rc, m_szFailInfo); + goto Exit; + } + + // Verify that we get back the expected data. + // Set the test number to a different value than the passed in value to + // ensure that we are actually changing it in the get call. + + i64TestNum = i64Num + 1; + if (RC_BAD( rc = pDataRec->getINT64( pvDataField, &i64TestNum))) + { + f_sprintf( szErr, "calling getINT64 for Signed64 value %I64d", i64Num); + MAKE_ERROR_STRING( szErr, rc, m_szFailInfo); + goto Exit; + } + if (i64TestNum != i64Num) + { + rc = RC_SET( FERR_FAILURE); + f_sprintf( m_szFailInfo, + "Signed64 value set not retrieved, Set: %I64d, Retrieved: %I64d", + i64Num, i64TestNum); + goto Exit; + } + + uiDrn = 0; + if( RC_BAD( rc = FlmRecordAdd( m_hDb, FLM_DATA_CONTAINER, + &uiDrn, pDataRec, 0))) + { + MAKE_ERROR_STRING( "calling FlmRecordAdd", rc, m_szFailInfo); + goto Exit; + } + if (puiDrn) + { + *puiDrn = uiDrn; + } + +Exit: + + if (pDataRec) + { + pDataRec->Release(); + } + + return( rc); +} + +/*************************************************************************** +Desc: +****************************************************************************/ +RCODE IFlmTestImpl::numbersTest( + FLMUINT * puiDrn) +{ + RCODE rc = FERR_OK; + FLMBOOL bPassed = FALSE; + FLMBOOL bTransActive = FALSE; + FLMUINT uiLoop; + FLMUINT_TEST * pFLMUINTTest; + FLMUINT64_TEST * pFLMUINT64Test; + FLMINT_TEST * pFLMINTTest; + FLMINT64_TEST * pFLMINT64Test; + + beginTest( "64 Bit Numbers Test"); + + // Start an update transaction + + if( RC_BAD( rc = FlmDbTransBegin( m_hDb, FLM_UPDATE_TRANS, FLM_NO_TIMEOUT))) + { + MAKE_ERROR_STRING( "calling FlmDbTransBegin", rc, m_szFailInfo); + goto Exit; + } + bTransActive = TRUE; + + for (uiLoop = 0, pFLMUINTTest = &gv_FLMUINTTests [0]; + uiLoop < NUM_FLMUINT_TESTS; + uiLoop++, pFLMUINTTest++) + { + if (RC_BAD( rc = addRecWithFLMUINT( pFLMUINTTest->uiNum, puiDrn))) + { + goto Exit; + } + + // Don't want to get anything except the first DRN + + puiDrn = NULL; + } + for (uiLoop = 0, pFLMINTTest = &gv_FLMINTTests [0]; + uiLoop < NUM_FLMINT_TESTS; + uiLoop++, pFLMINTTest++) + { + if (RC_BAD( rc = addRecWithFLMINT( pFLMINTTest->iNum, puiDrn))) + { + goto Exit; + } + // Don't want to get anything except the first DRN + + puiDrn = NULL; + } + for (uiLoop = 0, pFLMUINT64Test = &gv_FLMUINT64Tests [0]; + uiLoop < NUM_FLMUINT64_TESTS; + uiLoop++, pFLMUINT64Test++) + { + if (RC_BAD( rc = addRecWithFLMUINT64( pFLMUINT64Test->ui64Num, puiDrn))) + { + goto Exit; + } + + // Don't want to get anything except the first DRN + + puiDrn = NULL; + } + for (uiLoop = 0, pFLMINT64Test = &gv_FLMINT64Tests [0]; + uiLoop < NUM_FLMINT64_TESTS; + uiLoop++, pFLMINT64Test++) + { + if (RC_BAD( rc = addRecWithFLMINT64( pFLMINT64Test->i64Num, puiDrn))) + { + goto Exit; + } + + // Don't want to get anything except the first DRN + + puiDrn = NULL; + } + + if( RC_BAD( rc = FlmDbTransCommit( m_hDb))) + { + MAKE_ERROR_STRING( "calling FlmDbTransCommit", rc, m_szFailInfo); + goto Exit; + } + bTransActive = FALSE; + + bPassed = TRUE; + +Exit: + + if (bTransActive) + { + (void)FlmDbTransAbort( m_hDb); + } + + endTest( bPassed); + return( rc); +} + +/*************************************************************************** +Desc: +****************************************************************************/ +RCODE IFlmTestImpl::testNumField( + FLMUINT * puiDrn, + FLMUINT uiExpectedNum, + RCODE rcExpectedUINT, + FLMINT iExpectedNum, + RCODE rcExpectedINT, + FLMUINT64 ui64ExpectedNum, + RCODE rcExpectedUINT64, + FLMINT64 i64ExpectedNum, + RCODE rcExpectedINT64) +{ + RCODE rc = FERR_OK; + FLMUINT uiNum; + FLMINT iNum; + FLMUINT64 ui64Num; + FLMINT64 i64Num; + FlmRecord * pDataRec = NULL; + void * pvField; + FLMUINT uiDrn; + + if (RC_BAD( rc = FlmRecordRetrieve( m_hDb, FLM_DATA_CONTAINER, *puiDrn, + FO_EXACT, &pDataRec, &uiDrn))) + { + MAKE_ERROR_STRING( "calling FlmRecordRetrieve", rc, m_szFailInfo); + goto Exit; + } + (*puiDrn)++; + + pvField = pDataRec->firstChild( pDataRec->root()); + + // Test FLMUINT - set number different from expected number so we can verify + // that we actually changed the value. + + uiNum = uiExpectedNum + 1; + rc = pDataRec->getUINT( pvField, &uiNum); + if (rc != rcExpectedUINT) + { + f_sprintf( m_szFailInfo, "Unexpected rc (%e) from getUINT, expected %e. Num: %u", + rc, rcExpectedUINT, (unsigned)uiExpectedNum); + if (rc == FERR_OK) + { + rc = RC_SET( FERR_FAILURE); + } + goto Exit; + } + else if (RC_OK( rc)) + { + if (uiNum != uiExpectedNum) + { + rc = RC_SET( FERR_FAILURE); + f_sprintf( m_szFailInfo, "Unexpected UINT (%u) from getUINT, expected %u", + (unsigned)uiNum, (unsigned)uiExpectedNum); + goto Exit; + } + } + else + { + // Need to set to FERR_OK, even though we expected it to fail, + // so the caller will not exit. + + rc = FERR_OK; + } + + // Test FLMINT - set number different from expected number so we can verify + // that we actually changed the value. + + iNum = iExpectedNum + 1; + rc = pDataRec->getINT( pvField, &iNum); + if (rc != rcExpectedINT) + { + f_sprintf( m_szFailInfo, "Unexpected rc (%e) from getINT, expected %e. Num: %d", + rc, rcExpectedINT, (int)iExpectedNum); + if (rc == FERR_OK) + { + rc = RC_SET( FERR_FAILURE); + } + goto Exit; + } + else if (RC_OK( rc)) + { + if (iNum != iExpectedNum) + { + rc = RC_SET( FERR_FAILURE); + f_sprintf( m_szFailInfo, "Unexpected INT (%d) from getINT, expected %d", + (int)iNum, (int)iExpectedNum); + goto Exit; + } + } + else + { + // Need to set to FERR_OK, even though we expected it to fail, + // so the caller will not exit. + + rc = FERR_OK; + } + + // Test FLMUINT64 - set number different from expected number so we can verify + // that we actually changed the value. + + ui64Num = ui64ExpectedNum + 1; + rc = pDataRec->getUINT64( pvField, &ui64Num); + if (rc != rcExpectedUINT64) + { + f_sprintf( m_szFailInfo, "Unexpected rc (%e) from getUINT64, expected %e. Num: %I64u", + rc, rcExpectedUINT64, ui64ExpectedNum); + if (rc == FERR_OK) + { + rc = RC_SET( FERR_FAILURE); + } + goto Exit; + } + else if (RC_OK( rc)) + { + if (ui64Num != ui64ExpectedNum) + { + rc = RC_SET( FERR_FAILURE); + f_sprintf( m_szFailInfo, "Unexpected UINT64 (%I64u) from getUINT64, expected %I64u", + ui64Num, ui64ExpectedNum); + goto Exit; + } + } + else + { + // Need to set to FERR_OK, even though we expected it to fail, + // so the caller will not exit. + + rc = FERR_OK; + } + + // Test FLMINT64 - set number different from expected number so we can verify + // that we actually changed the value. + + i64Num = i64ExpectedNum + 1; + rc = pDataRec->getINT64( pvField, &i64Num); + if (rc != rcExpectedINT64) + { + f_sprintf( m_szFailInfo, "Unexpected rc (%e) from getINT64, expected %e. Num: %I64d", + rc, rcExpectedINT64, i64ExpectedNum); + if (rc == FERR_OK) + { + rc = RC_SET( FERR_FAILURE); + } + goto Exit; + } + else if (RC_OK( rc)) + { + if (i64Num != i64ExpectedNum) + { + rc = RC_SET( FERR_FAILURE); + f_sprintf( m_szFailInfo, "Unexpected INT64 (%I64d) from getINT64, expected %I64d", + i64Num, i64ExpectedNum); + goto Exit; + } + } + else + { + // Need to set to FERR_OK, even though we expected it to fail, + // so the caller will not exit. + + rc = FERR_OK; + } + +Exit: + + if (pDataRec) + { + pDataRec->Release(); + } + + return( rc); +} + +/*************************************************************************** +Desc: +****************************************************************************/ +RCODE IFlmTestImpl::numbersRetrieveTest( + FLMUINT uiDrn) +{ + RCODE rc = FERR_OK; + FLMBOOL bPassed = FALSE; + FLMUINT uiLoop; + FLMUINT_TEST * pFLMUINTTest; + FLMUINT64_TEST * pFLMUINT64Test; + FLMINT_TEST * pFLMINTTest; + FLMINT64_TEST * pFLMINT64Test; + + beginTest( "64 Bit Numbers Query Test"); + + for (uiLoop = 0, pFLMUINTTest = &gv_FLMUINTTests [0]; + uiLoop < NUM_FLMUINT_TESTS; + uiLoop++, pFLMUINTTest++) + { + if (RC_BAD( rc = testNumField( &uiDrn, + (FLMUINT)pFLMUINTTest->uiNum, pFLMUINTTest->rcExpectedGetUINT, + (FLMINT)pFLMUINTTest->uiNum, pFLMUINTTest->rcExpectedGetINT, + (FLMUINT64)pFLMUINTTest->uiNum, pFLMUINTTest->rcExpectedGetUINT64, + (FLMINT64)pFLMUINTTest->uiNum, pFLMUINTTest->rcExpectedGetINT64))) + { + goto Exit; + } + } + for (uiLoop = 0, pFLMINTTest = &gv_FLMINTTests [0]; + uiLoop < NUM_FLMINT_TESTS; + uiLoop++, pFLMINTTest++) + { + if (RC_BAD( rc = testNumField( &uiDrn, + (FLMUINT)pFLMINTTest->iNum, pFLMINTTest->rcExpectedGetUINT, + (FLMINT)pFLMINTTest->iNum, pFLMINTTest->rcExpectedGetINT, + (FLMUINT64)pFLMINTTest->iNum, pFLMINTTest->rcExpectedGetUINT64, + (FLMINT64)pFLMINTTest->iNum, pFLMINTTest->rcExpectedGetINT64))) + { + goto Exit; + } + } + for (uiLoop = 0, pFLMUINT64Test = &gv_FLMUINT64Tests [0]; + uiLoop < NUM_FLMUINT64_TESTS; + uiLoop++, pFLMUINT64Test++) + { + if (RC_BAD( rc = testNumField( &uiDrn, + (FLMUINT)pFLMUINT64Test->ui64Num, pFLMUINT64Test->rcExpectedGetUINT, + (FLMINT)pFLMUINT64Test->ui64Num, pFLMUINT64Test->rcExpectedGetINT, + (FLMUINT64)pFLMUINT64Test->ui64Num, pFLMUINT64Test->rcExpectedGetUINT64, + (FLMINT64)pFLMUINT64Test->ui64Num, pFLMUINT64Test->rcExpectedGetINT64))) + { + goto Exit; + } + } + for (uiLoop = 0, pFLMINT64Test = &gv_FLMINT64Tests [0]; + uiLoop < NUM_FLMINT64_TESTS; + uiLoop++, pFLMINT64Test++) + { + if (RC_BAD( rc = testNumField( &uiDrn, + (FLMUINT)pFLMINT64Test->i64Num, pFLMINT64Test->rcExpectedGetUINT, + (FLMINT)pFLMINT64Test->i64Num, pFLMINT64Test->rcExpectedGetINT, + (FLMUINT64)pFLMINT64Test->i64Num, pFLMINT64Test->rcExpectedGetUINT64, + (FLMINT64)pFLMINT64Test->i64Num, pFLMINT64Test->rcExpectedGetINT64))) + { + goto Exit; + } + } + + bPassed = TRUE; + +Exit: + + endTest( bPassed); + return( rc); +} + +/*************************************************************************** +Desc: +****************************************************************************/ +RCODE IFlmTestImpl::numbersKeyRetrieveTest( void) +{ + RCODE rc = FERR_OK; + FLMBOOL bPassed = FALSE; + FLMUINT uiFlags = FO_FIRST; + FlmRecord * pSearchKey = NULL; + FlmRecord * pFoundKey = NULL; + FLMUINT uiFoundDrn = 0; + void * pvField; + FLMUINT uiCurrKey = 0; + FLMUINT64 ui64Num; + FLMINT64 i64Num; + + beginTest( "Numbers FlmKeyRetrieve Test"); + for (;;) + { + if (RC_BAD( rc = FlmKeyRetrieve( m_hDb, NUMBER_IX, + 0, pSearchKey, 0, uiFlags, + &pFoundKey, &uiFoundDrn))) + { + if (rc == FERR_EOF_HIT) + { + if (uiCurrKey != NUM_NUM_KEYS) + { + rc = RC_SET( FERR_DATA_ERROR); + f_sprintf( m_szFailInfo, "Unexpected number of keys in index: %u, Expected %u", + (unsigned)uiCurrKey, (unsigned)NUM_NUM_KEYS); + goto Exit; + } + rc = FERR_OK; + break; + } + else + { + MAKE_ERROR_STRING( "calling FlmKeyRetrieve", rc, m_szFailInfo); + goto Exit; + } + } + + // Make sure we have not matched all of the expected keys yet. + + if (uiCurrKey == NUM_NUM_KEYS) + { + rc = RC_SET( FERR_DATA_ERROR); + f_sprintf( m_szFailInfo, "Too many keys in index, only expecting %u", + (unsigned)NUM_NUM_KEYS); + goto Exit; + } + + // Make sure this key is greater than the last key. + + if ((pvField = pFoundKey->find( pFoundKey->root(), NUMBER_TAG)) == NULL) + { + rc = RC_SET( FERR_DATA_ERROR); + MAKE_ERROR_STRING( "corruption calling FlmRecord->find()", + rc, m_szFailInfo); + goto Exit; + } + + if (gv_ExpectedNumIxValues [uiCurrKey].bUnsigned) + { + if (RC_BAD( rc = pFoundKey->getUINT64( pvField, &ui64Num))) + { + MAKE_ERROR_STRING( "calling FlmRecord->getUINT64", rc, m_szFailInfo); + goto Exit; + } + if (ui64Num != gv_ExpectedNumIxValues [uiCurrKey].ui64Value) + { + rc = RC_SET( FERR_DATA_ERROR); + f_sprintf( m_szFailInfo, "Unexpected unsigned value in index key[%u]: %I64u, Expected: %I64u", + (unsigned)uiCurrKey, ui64Num, gv_ExpectedNumIxValues [uiCurrKey].ui64Value); + goto Exit; + } + } + else + { + if (RC_BAD( rc = pFoundKey->getINT64( pvField, &i64Num))) + { + MAKE_ERROR_STRING( "calling FlmRecord->getINT64", rc, m_szFailInfo); + goto Exit; + } + if (i64Num != gv_ExpectedNumIxValues [uiCurrKey].i64Value) + { + rc = RC_SET( FERR_DATA_ERROR); + f_sprintf( m_szFailInfo, "Unexpected signed value in index key[%u]: %I64d, Expected: %I64d", + (unsigned)uiCurrKey, i64Num, gv_ExpectedNumIxValues [uiCurrKey].i64Value); + goto Exit; + } + } + + // Setup to get the next key. + + uiCurrKey++; + uiFlags = FO_EXCL; + if (pSearchKey) + { + pSearchKey->Release(); + } + pSearchKey = pFoundKey; + pFoundKey = NULL; + uiFoundDrn = 0; + } + bPassed = TRUE; + +Exit: + + if (pSearchKey) + { + pSearchKey->Release(); + } + if (pFoundKey) + { + pFoundKey->Release(); + } + + endTest( bPassed); + return( rc); +} + +/*************************************************************************** +Desc: +****************************************************************************/ +RCODE IFlmTestImpl::reopenDbTest( void) +{ + RCODE rc = FERR_OK; + FLMBOOL bPassed = FALSE; + char szDbName [F_PATH_MAX_SIZE]; + + beginTest( "Close & Reopen Database Test"); + + // Close the database + + if (RC_BAD( rc = FlmDbClose( &m_hDb))) + { + MAKE_ERROR_STRING( "calling FlmDbClose", rc, m_szFailInfo); + goto Exit; + } + + // Force everything to really close. + + f_strcpy( szDbName, DB_NAME_STR); + if (RC_BAD( rc = FlmConfig( FLM_CLOSE_FILE, (void *)&szDbName [0], NULL))) + { + MAKE_ERROR_STRING( "calling FlmConfig(FLM_CLOSE_FILE)", rc, m_szFailInfo); + goto Exit; + } + + // Force everything from cache. + + if (RC_BAD( rc = FlmConfig( FLM_CLOSE_UNUSED_FILES, (void *)0, (void *)0))) + { + MAKE_ERROR_STRING( "calling FlmConfig(FLM_CLOSE_UNUSED_FILES)", rc, m_szFailInfo); + goto Exit; + } + + // Reopen the database. + + if( RC_BAD( rc = FlmDbOpen( DB_NAME_STR, NULL, NULL, + FO_DONT_RESUME_BACKGROUND_THREADS, NULL, &m_hDb))) + { + MAKE_ERROR_STRING( "calling FlmDbOpen", rc, m_szFailInfo); + goto Exit; + } + + bPassed = TRUE; + +Exit: + + endTest( bPassed); + + return( rc); +} + /*************************************************************************** Desc: ****************************************************************************/ @@ -3767,6 +4843,35 @@ RCODE IFlmTestImpl::execute( void) goto Exit; } + // Numbers test + + if (RC_BAD( rc = numbersTest( &uiDrn))) + { + goto Exit; + } + + // Close and reopen the database to force everything to be written to + // disk and to have things removed from cache. + + if (RC_BAD( rc = reopenDbTest())) + { + goto Exit; + } + + // Numbers query test. + + if (RC_BAD( rc = numbersRetrieveTest( uiDrn))) + { + goto Exit; + } + + // Numbers key retrieve test. + + if (RC_BAD( rc = numbersKeyRetrieveTest())) + { + goto Exit; + } + // Hot Backup/Restore test if (RC_BAD( rc = backupRestoreDbTest()))