Files
mars-flaim/xflaim/src/fqeval.cpp
dsandersoremutah c55dab446f Renamed version4 to flaim and version5 to xflaim
git-svn-id: https://svn.code.sf.net/p/flaim/code/trunk@7 0109f412-320b-0410-ab79-c3e0c5ffbbe6
2006-01-27 21:06:39 +00:00

2567 lines
56 KiB
C++

//------------------------------------------------------------------------------
// Desc: Contains the methods for doing evaluation of query expressions.
//
// Tabs: 3
//
// Copyright (c) 2003-2006 Novell, Inc. All Rights Reserved.
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of version 2 of the GNU General Public
// License as published by the Free Software Foundation.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, contact Novell, Inc.
//
// To contact Novell about this file by physical or electronic mail,
// you may find current contact information at www.novell.com
//
// $Id: fqeval.cpp 3114 2006-01-19 13:22:45 -0700 (Thu, 19 Jan 2006) dsanders $
//------------------------------------------------------------------------------
#include "flaimsys.h"
#include "fquery.h"
FSTATIC RCODE fqApproxCompare(
FQVALUE * pLValue,
FQVALUE * pRValue,
FLMINT * piResult);
FSTATIC RCODE fqCompareBinary(
IF_OperandComparer * pOpComparer,
FQVALUE * pLValue,
FQVALUE * pRValue,
FLMINT * piResult);
FSTATIC RCODE fqCompareText(
IF_OperandComparer * pOpComparer,
FQVALUE * pLValue,
FQVALUE * pRValue,
FLMUINT uiCompareRules,
FLMBOOL bOpIsMatch,
FLMUINT uiLanguage,
FLMINT * piResult);
FSTATIC void fqOpUUBitAND(
FQVALUE * pLValue,
FQVALUE * pRValue,
FQVALUE * pResult);
FSTATIC void fqOpUUBitOR(
FQVALUE * pLValue,
FQVALUE * pRValue,
FQVALUE * pResult);
FSTATIC void fqOpUUBitXOR(
FQVALUE * pLValue,
FQVALUE * pRValue,
FQVALUE * pResult);
FSTATIC void fqOpUUMult(
FQVALUE * pLValue,
FQVALUE * pRValue,
FQVALUE * pResult);
FSTATIC void fqOpUSMult(
FQVALUE * pLValue,
FQVALUE * pRValue,
FQVALUE * pResult);
FSTATIC void fqOpSSMult(
FQVALUE * pLValue,
FQVALUE * pRValue,
FQVALUE * pResult);
FSTATIC void fqOpSUMult(
FQVALUE * pLValue,
FQVALUE * pRValue,
FQVALUE * pResult);
FSTATIC void fqOpUUDiv(
FQVALUE * pLValue,
FQVALUE * pRValue,
FQVALUE * pResult);
FSTATIC void fqOpUSDiv(
FQVALUE * pLValue,
FQVALUE * pRValue,
FQVALUE * pResult);
FSTATIC void fqOpSSDiv(
FQVALUE * pLValue,
FQVALUE * pRValue,
FQVALUE * pResult);
FSTATIC void fqOpSUDiv(
FQVALUE * pLValue,
FQVALUE * pRValue,
FQVALUE * pResult);
FSTATIC void fqOpUUMod(
FQVALUE * pLValue,
FQVALUE * pRValue,
FQVALUE * pResult);
FSTATIC void fqOpUSMod(
FQVALUE * pLValue,
FQVALUE * pRValue,
FQVALUE * pResult);
FSTATIC void fqOpSSMod(
FQVALUE * pLValue,
FQVALUE * pRValue,
FQVALUE * pResult);
FSTATIC void fqOpSUMod(
FQVALUE * pLValue,
FQVALUE * pRValue,
FQVALUE * pResult);
FSTATIC void fqOpUUPlus(
FQVALUE * pLValue,
FQVALUE * pRValue,
FQVALUE * pResult);
FSTATIC void fqOpUSPlus(
FQVALUE * pLValue,
FQVALUE * pRValue,
FQVALUE * pResult);
FSTATIC void fqOpSSPlus(
FQVALUE * pLValue,
FQVALUE * pRValue,
FQVALUE * pResult);
FSTATIC void fqOpSUPlus(
FQVALUE * pLValue,
FQVALUE * pRValue,
FQVALUE * pResult);
FSTATIC void fqOpUUMinus(
FQVALUE * pLValue,
FQVALUE * pRValue,
FQVALUE * pResult);
FSTATIC void fqOpUSMinus(
FQVALUE * pLValue,
FQVALUE * pRValue,
FQVALUE * pResult);
FSTATIC void fqOpSSMinus(
FQVALUE * pLValue,
FQVALUE * pRValue,
FQVALUE * pResult);
FSTATIC void fqOpSUMinus(
FQVALUE * pLValue,
FQVALUE * pRValue,
FQVALUE * pResult);
typedef void FQ_OPERATION(
FQVALUE * pLValue,
FQVALUE * pRValue,
FQVALUE * pResult);
FQ_OPERATION * FQ_ArithOpTable[
((XFLM_LAST_ARITH_OP - XFLM_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: Returns a 64-bit unsigned integer
***************************************************************************/
FINLINE FLMUINT64 fqGetUInt64(
FQVALUE * pValue)
{
if (pValue->eValType == XFLM_UINT_VAL)
{
return( (FLMUINT64)pValue->val.uiVal);
}
else if( pValue->eValType == XFLM_UINT64_VAL)
{
return( pValue->val.ui64Val);
}
else if( pValue->eValType == XFLM_INT64_VAL)
{
if( pValue->val.i64Val >= 0)
{
return( (FLMUINT64)pValue->val.i64Val);
}
}
else if( pValue->eValType == XFLM_INT_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(
FQVALUE * pValue)
{
if (pValue->eValType == XFLM_INT_VAL)
{
return( (FLMINT64)pValue->val.iVal);
}
else if( pValue->eValType == XFLM_INT64_VAL)
{
return( pValue->val.i64Val);
}
else if( pValue->eValType == XFLM_UINT_VAL)
{
return( (FLMINT64)pValue->val.uiVal);
}
else if( pValue->eValType == XFLM_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(
FQVALUE * pLValue,
FQVALUE * pRValue,
FQVALUE * pResult)
{
if( isNativeNum( pLValue->eValType) &&
isNativeNum( pRValue->eValType))
{
pResult->val.uiVal = pLValue->val.uiVal & pRValue->val.uiVal;
pResult->eValType = XFLM_UINT_VAL;
}
else
{
pResult->val.ui64Val =
fqGetUInt64( pLValue) & fqGetUInt64( pRValue);
pResult->eValType = XFLM_UINT64_VAL;
}
}
/***************************************************************************
Desc: Performs the bit or operation
***************************************************************************/
FSTATIC void fqOpUUBitOR(
FQVALUE * pLValue,
FQVALUE * pRValue,
FQVALUE * pResult)
{
if( isNativeNum( pLValue->eValType) &&
isNativeNum( pRValue->eValType))
{
pResult->val.uiVal = pLValue->val.uiVal | pRValue->val.uiVal;
pResult->eValType = XFLM_UINT_VAL;
}
else
{
pResult->val.ui64Val =
fqGetUInt64( pLValue) | fqGetUInt64( pRValue);
pResult->eValType = XFLM_UINT64_VAL;
}
}
/***************************************************************************
Desc: Performs the bit xor operation
***************************************************************************/
FSTATIC void fqOpUUBitXOR(
FQVALUE * pLValue,
FQVALUE * pRValue,
FQVALUE * pResult)
{
if( isNativeNum( pLValue->eValType) &&
isNativeNum( pRValue->eValType))
{
pResult->val.uiVal = pLValue->val.uiVal ^ pRValue->val.uiVal;
pResult->eValType = XFLM_UINT_VAL;
}
else
{
pResult->val.ui64Val =
fqGetUInt64( pLValue) ^ fqGetUInt64( pRValue);
pResult->eValType = XFLM_UINT64_VAL;
}
}
/***************************************************************************
Desc: Performs the multiply operation
***************************************************************************/
FSTATIC void fqOpUUMult(
FQVALUE * pLValue,
FQVALUE * pRValue,
FQVALUE * pResult)
{
if( isNativeNum( pLValue->eValType) &&
isNativeNum( pRValue->eValType))
{
pResult->val.uiVal = pLValue->val.uiVal * pRValue->val.uiVal;
pResult->eValType = XFLM_UINT_VAL;
}
else
{
pResult->val.ui64Val =
fqGetUInt64( pLValue) * fqGetUInt64( pRValue);
pResult->eValType = XFLM_UINT64_VAL;
}
}
/***************************************************************************
Desc: Performs the multiply operation
***************************************************************************/
FSTATIC void fqOpUSMult(
FQVALUE * pLValue,
FQVALUE * pRValue,
FQVALUE * pResult)
{
if( isNativeNum( pLValue->eValType) &&
isNativeNum( pRValue->eValType))
{
pResult->val.iVal = (FLMINT)pLValue->val.uiVal * pRValue->val.iVal;
pResult->eValType = XFLM_INT_VAL;
}
else
{
pResult->val.i64Val = (FLMINT64)
fqGetUInt64( pLValue) * fqGetInt64( pRValue);
pResult->eValType = XFLM_INT64_VAL;
}
}
/***************************************************************************
Desc: Performs the multiply operation
***************************************************************************/
FSTATIC void fqOpSSMult(
FQVALUE * pLValue,
FQVALUE * pRValue,
FQVALUE * pResult)
{
if( isNativeNum( pLValue->eValType) &&
isNativeNum( pRValue->eValType))
{
pResult->val.iVal = pLValue->val.iVal * pRValue->val.iVal;
pResult->eValType = (pResult->val.iVal < 0)
? XFLM_INT_VAL
: XFLM_UINT_VAL;
}
else
{
pResult->val.i64Val = (FLMINT64)(fqGetInt64( pLValue) *
fqGetInt64( pRValue));
pResult->eValType = (pResult->val.i64Val < 0)
? XFLM_INT64_VAL
: XFLM_UINT64_VAL;
}
}
/***************************************************************************
Desc: Performs the multiply operation
***************************************************************************/
FSTATIC void fqOpSUMult(
FQVALUE * pLValue,
FQVALUE * pRValue,
FQVALUE * pResult)
{
if( isNativeNum( pLValue->eValType) &&
isNativeNum( pRValue->eValType))
{
pResult->val.iVal = pLValue->val.iVal *
(FLMINT)pRValue->val.uiVal;
pResult->eValType = XFLM_INT_VAL;
}
else
{
pResult->val.i64Val = (FLMINT64)
(fqGetInt64( pLValue) * fqGetUInt64( pRValue));
pResult->eValType = XFLM_INT64_VAL;
}
}
/***************************************************************************
Desc: Performs the divide operation
***************************************************************************/
FSTATIC void fqOpUUDiv(
FQVALUE * pLValue,
FQVALUE * pRValue,
FQVALUE * pResult)
{
if( isNativeNum( pLValue->eValType) &&
isNativeNum( pRValue->eValType))
{
if( pRValue->val.uiVal)
{
pResult->val.uiVal = pLValue->val.uiVal / pRValue->val.uiVal;
pResult->eValType = XFLM_UINT_VAL;
}
else
{
pResult->val.uiVal = 0; // Divide by ZERO case.
pResult->eValType = XFLM_MISSING_VAL;
}
}
else
{
FLMUINT64 ui64LValue = fqGetUInt64( pLValue);
FLMUINT64 ui64RValue = fqGetUInt64( pRValue);
if( ui64RValue)
{
pResult->val.ui64Val = ui64LValue / ui64RValue;
pResult->eValType = XFLM_UINT64_VAL;
}
else
{
pResult->val.uiVal = 0; // Divide by ZERO case.
pResult->eValType = XFLM_MISSING_VAL;
}
}
}
/***************************************************************************
Desc: Performs the divide operation
***************************************************************************/
FSTATIC void fqOpUSDiv(
FQVALUE * pLValue,
FQVALUE * pRValue,
FQVALUE * pResult)
{
if( isNativeNum( pLValue->eValType) &&
isNativeNum( pRValue->eValType))
{
if( pRValue->val.iVal)
{
pResult->val.iVal = pLValue->val.uiVal / pRValue->val.iVal;
pResult->eValType = XFLM_INT_VAL;
}
else
{
pResult->val.uiVal = 0; // Divide by ZERO case.
pResult->eValType = XFLM_MISSING_VAL;
}
}
else
{
FLMUINT64 ui64LValue = fqGetUInt64( pLValue);
FLMINT64 i64RValue = fqGetInt64( pRValue);
if( i64RValue)
{
pResult->val.i64Val = ui64LValue / i64RValue;
pResult->eValType = XFLM_INT64_VAL;
}
else
{
pResult->val.uiVal = 0; // Divide by ZERO case.
pResult->eValType = XFLM_MISSING_VAL;
}
}
}
/***************************************************************************
Desc: Performs the divide operation
***************************************************************************/
FSTATIC void fqOpSSDiv(
FQVALUE * pLValue,
FQVALUE * pRValue,
FQVALUE * pResult)
{
if( isNativeNum( pLValue->eValType) &&
isNativeNum( pRValue->eValType))
{
if( pRValue->val.iVal)
{
pResult->val.iVal = pLValue->val.iVal / pRValue->val.iVal;
pResult->eValType = (pResult->val.iVal < 0)
? XFLM_INT_VAL : XFLM_UINT_VAL;
}
else
{
pResult->val.uiVal = 0; // Divide by ZERO case.
pResult->eValType = XFLM_MISSING_VAL;
}
}
else
{
FLMINT64 i64LValue = fqGetInt64( pLValue);
FLMINT64 i64RValue = fqGetInt64( pRValue);
if( i64RValue)
{
pResult->val.i64Val = i64LValue / i64RValue;
pResult->eValType = (pResult->val.i64Val < 0)
? XFLM_INT64_VAL : XFLM_UINT64_VAL;
}
else
{
pResult->val.uiVal = 0; // Divide by ZERO case.
pResult->eValType = XFLM_MISSING_VAL;
}
}
}
/***************************************************************************
Desc: Performs the divide operation
***************************************************************************/
FSTATIC void fqOpSUDiv(
FQVALUE * pLValue,
FQVALUE * pRValue,
FQVALUE * pResult)
{
if( isNativeNum( pLValue->eValType) &&
isNativeNum( pRValue->eValType))
{
if( pRValue->val.uiVal)
{
pResult->val.iVal = pLValue->val.iVal / pRValue->val.uiVal;
pResult->eValType = XFLM_INT_VAL;
}
else
{
pResult->val.uiVal = 0; // Divide by ZERO case.
pResult->eValType = XFLM_MISSING_VAL;
}
}
else
{
FLMINT64 i64LValue = fqGetInt64( pLValue);
FLMUINT64 ui64RValue = fqGetUInt64( pRValue);
if( ui64RValue)
{
pResult->val.i64Val = i64LValue / ui64RValue;
pResult->eValType = XFLM_INT64_VAL;
}
else
{
pResult->val.uiVal = 0; // Divide by ZERO case.
pResult->eValType = XFLM_MISSING_VAL;
}
}
}
/***************************************************************************
Desc: Performs the modulo operation
***************************************************************************/
FSTATIC void fqOpUUMod(
FQVALUE * pLValue,
FQVALUE * pRValue,
FQVALUE * pResult)
{
if( isNativeNum( pLValue->eValType) &&
isNativeNum( pRValue->eValType))
{
if( pRValue->val.uiVal)
{
pResult->val.uiVal = pLValue->val.uiVal % pRValue->val.uiVal;
pResult->eValType = XFLM_UINT_VAL;
}
else
{
pResult->val.uiVal = 0; // MOD by ZERO case.
pResult->eValType = XFLM_MISSING_VAL;
}
}
else
{
FLMUINT64 ui64LValue = fqGetUInt64( pLValue);
FLMUINT64 ui64RValue = fqGetUInt64( pRValue);
if( ui64RValue)
{
pResult->val.ui64Val = ui64LValue % ui64RValue;
pResult->eValType = XFLM_UINT64_VAL;
}
else
{
pResult->val.uiVal = 0; // MOD by ZERO case.
pResult->eValType = XFLM_MISSING_VAL;
}
}
}
/***************************************************************************
Desc: Performs the modulo operation
***************************************************************************/
FSTATIC void fqOpUSMod(
FQVALUE * pLValue,
FQVALUE * pRValue,
FQVALUE * pResult)
{
if( isNativeNum( pLValue->eValType) &&
isNativeNum( pRValue->eValType))
{
if( pRValue->val.iVal)
{
pResult->val.iVal = pLValue->val.uiVal % pRValue->val.iVal;
pResult->eValType = XFLM_INT_VAL;
}
else
{
pResult->val.uiVal = 0; // MOD by ZERO case.
pResult->eValType = XFLM_MISSING_VAL;
}
}
else
{
FLMUINT64 ui64LValue = fqGetUInt64( pLValue);
FLMINT64 i64RValue = fqGetInt64( pRValue);
if( i64RValue)
{
pResult->val.i64Val = ui64LValue % i64RValue;
pResult->eValType = XFLM_INT64_VAL;
}
else
{
pResult->val.uiVal = 0; // MOD by ZERO case.
pResult->eValType = XFLM_MISSING_VAL;
}
}
}
/***************************************************************************
Desc: Performs the modulo operation
***************************************************************************/
FSTATIC void fqOpSSMod(
FQVALUE * pLValue,
FQVALUE * pRValue,
FQVALUE * pResult)
{
if( isNativeNum( pLValue->eValType) &&
isNativeNum( pRValue->eValType))
{
if( pRValue->val.iVal)
{
pResult->val.iVal = pLValue->val.iVal % pRValue->val.iVal;
pResult->eValType = (pResult->val.iVal < 0)
? XFLM_INT_VAL : XFLM_UINT_VAL;
}
else
{
pResult->val.uiVal = 0; // MOD by ZERO case.
pResult->eValType = XFLM_MISSING_VAL;
}
}
else
{
FLMINT64 i64LValue = fqGetInt64( pLValue);
FLMINT64 i64RValue = fqGetInt64( pRValue);
if( i64RValue)
{
pResult->val.i64Val = i64LValue % i64RValue;
pResult->eValType = (pResult->val.i64Val < 0)
? XFLM_INT64_VAL : XFLM_UINT64_VAL;
}
else
{
pResult->val.uiVal = 0; // MOD by ZERO case.
pResult->eValType = XFLM_MISSING_VAL;
}
}
}
/***************************************************************************
Desc: Performs the modulo operation
***************************************************************************/
FSTATIC void fqOpSUMod(
FQVALUE * pLValue,
FQVALUE * pRValue,
FQVALUE * pResult)
{
if( isNativeNum( pLValue->eValType) &&
isNativeNum( pRValue->eValType))
{
if( pRValue->val.uiVal)
{
pResult->val.iVal = pLValue->val.iVal % pRValue->val.uiVal;
pResult->eValType = XFLM_INT_VAL;
}
else
{
pResult->val.uiVal = 0; // MOD by ZERO case.
pResult->eValType = XFLM_MISSING_VAL;
}
}
else
{
FLMINT64 i64LValue = fqGetInt64( pLValue);
FLMUINT64 ui64RValue = fqGetUInt64( pRValue);
if( ui64RValue)
{
pResult->val.i64Val = i64LValue % ui64RValue;
pResult->eValType = XFLM_INT64_VAL;
}
else
{
pResult->val.uiVal = 0; // MOD by ZERO case.
pResult->eValType = XFLM_MISSING_VAL;
}
}
}
/***************************************************************************
Desc: Performs an addition operation
***************************************************************************/
FSTATIC void fqOpUUPlus(
FQVALUE * pLValue,
FQVALUE * pRValue,
FQVALUE * pResult)
{
if( isNativeNum( pLValue->eValType) &&
isNativeNum( pRValue->eValType))
{
pResult->val.uiVal = pLValue->val.uiVal + pRValue->val.uiVal;
pResult->eValType = XFLM_UINT_VAL;
}
else
{
pResult->val.ui64Val =
fqGetUInt64( pLValue) + fqGetUInt64( pRValue);
pResult->eValType = XFLM_UINT64_VAL;
}
}
/***************************************************************************
Desc: Performs an addition operation
***************************************************************************/
FSTATIC void fqOpUSPlus(
FQVALUE * pLValue,
FQVALUE * pRValue,
FQVALUE * pResult)
{
if( isNativeNum( pLValue->eValType) &&
isNativeNum( pRValue->eValType))
{
if( (pRValue->val.iVal >= 0) ||
(pLValue->val.uiVal > gv_uiMaxSignedIntVal))
{
pResult->val.uiVal = pLValue->val.uiVal + (FLMUINT)pRValue->val.iVal;
pResult->eValType = XFLM_UINT_VAL;
}
else
{
pResult->val.iVal = (FLMINT)pLValue->val.uiVal + pRValue->val.iVal;
pResult->eValType = (pResult->val.iVal < 0)
? XFLM_INT_VAL : XFLM_UINT_VAL;
}
}
else
{
FLMUINT64 ui64LValue = fqGetUInt64( pLValue);
FLMINT64 i64RValue = fqGetInt64( pRValue);
if( (i64RValue >= 0) || (ui64LValue > gv_ui64MaxSignedIntVal))
{
pResult->val.ui64Val = ui64LValue + (FLMUINT64)i64RValue;
pResult->eValType = XFLM_UINT64_VAL;
}
else
{
pResult->val.i64Val = (FLMINT64)ui64LValue + i64RValue;
pResult->eValType = (pResult->val.i64Val < 0)
? XFLM_INT64_VAL : XFLM_UINT64_VAL;
}
}
}
/***************************************************************************
Desc: Performs an addition operation
***************************************************************************/
FSTATIC void fqOpSSPlus(
FQVALUE * pLValue,
FQVALUE * pRValue,
FQVALUE * pResult)
{
if( isNativeNum( pLValue->eValType) &&
isNativeNum( pRValue->eValType))
{
pResult->val.iVal = pLValue->val.iVal + pRValue->val.iVal;
pResult->eValType = (pResult->val.iVal < 0)
? XFLM_INT_VAL : XFLM_UINT_VAL;
}
else
{
pResult->val.i64Val =
fqGetInt64( pLValue) + fqGetInt64( pRValue);
pResult->eValType = (pResult->val.i64Val < 0)
? XFLM_INT64_VAL : XFLM_UINT64_VAL;
}
}
/***************************************************************************
Desc: Performs an addition operation
***************************************************************************/
FSTATIC void fqOpSUPlus(
FQVALUE * pLValue,
FQVALUE * pRValue,
FQVALUE * pResult)
{
if( isNativeNum( pLValue->eValType) &&
isNativeNum( pRValue->eValType))
{
if( (pLValue->val.iVal >= 0) ||
(pRValue->val.uiVal > gv_uiMaxSignedIntVal))
{
pResult->val.uiVal = (FLMUINT)pLValue->val.iVal + pRValue->val.uiVal;
pResult->eValType = XFLM_UINT_VAL;
}
else
{
pResult->val.iVal = pLValue->val.iVal + (FLMINT)pRValue->val.uiVal;
pResult->eValType = (pResult->val.iVal < 0)
? XFLM_INT_VAL : XFLM_UINT_VAL;
}
}
else
{
FLMINT64 i64LValue = fqGetInt64( pLValue);
FLMUINT64 ui64RValue = fqGetUInt64( pRValue);
if( (i64LValue >= 0) || (ui64RValue > gv_ui64MaxSignedIntVal))
{
pResult->val.ui64Val = (FLMUINT64)i64LValue + ui64RValue;
pResult->eValType = XFLM_UINT64_VAL;
}
else
{
pResult->val.i64Val = i64LValue + (FLMINT64)ui64RValue;
pResult->eValType = (pResult->val.i64Val < 0)
? XFLM_INT64_VAL : XFLM_UINT64_VAL;
}
}
}
/***************************************************************************
Desc: Performs a subtraction operation
***************************************************************************/
FSTATIC void fqOpUUMinus(
FQVALUE * pLValue,
FQVALUE * pRValue,
FQVALUE * pResult)
{
if( isNativeNum( pLValue->eValType) &&
isNativeNum( pRValue->eValType))
{
if( pLValue->val.uiVal >= pRValue->val.uiVal)
{
pResult->val.uiVal = pLValue->val.uiVal - pRValue->val.uiVal;
pResult->eValType = XFLM_UINT_VAL;
}
else
{
pResult->val.iVal = (FLMINT)(pLValue->val.uiVal - pRValue->val.uiVal);
pResult->eValType = XFLM_INT_VAL;
}
}
else
{
FLMUINT64 ui64LValue = fqGetUInt64( pLValue);
FLMUINT64 ui64RValue = fqGetUInt64( pRValue);
if( ui64LValue >= ui64RValue)
{
pResult->val.ui64Val = ui64LValue - ui64RValue;
pResult->eValType = XFLM_UINT64_VAL;
}
else
{
pResult->val.i64Val = (FLMINT64)(ui64LValue - ui64RValue);
pResult->eValType = XFLM_INT64_VAL;
}
}
}
/***************************************************************************
Desc: Performs a subtraction operation
***************************************************************************/
FSTATIC void fqOpUSMinus(
FQVALUE * pLValue,
FQVALUE * pRValue,
FQVALUE * pResult)
{
if( isNativeNum( pLValue->eValType) &&
isNativeNum( pRValue->eValType))
{
if( pRValue->val.iVal < 0)
{
pResult->val.uiVal = pLValue->val.uiVal - pRValue->val.iVal;
pResult->eValType = XFLM_UINT_VAL;
}
else
{
pResult->val.iVal = (FLMINT)pLValue->val.uiVal - pRValue->val.iVal;
pResult->eValType = (pResult->val.iVal < 0)
? XFLM_INT_VAL : XFLM_UINT_VAL;
}
}
else
{
FLMUINT64 ui64LValue = fqGetUInt64( pLValue);
FLMINT64 i64RValue = fqGetInt64( pRValue);
if( i64RValue < 0)
{
pResult->val.ui64Val = ui64LValue - i64RValue;
pResult->eValType = XFLM_UINT64_VAL;
}
else
{
pResult->val.i64Val = (FLMINT64)ui64LValue - i64RValue;
pResult->eValType = (pResult->val.i64Val < 0)
? XFLM_INT64_VAL : XFLM_UINT64_VAL;
}
}
}
/***************************************************************************
Desc: Performs a subtraction operation
***************************************************************************/
FSTATIC void fqOpSSMinus(
FQVALUE * pLValue,
FQVALUE * pRValue,
FQVALUE * pResult)
{
if( isNativeNum( pLValue->eValType) &&
isNativeNum( pRValue->eValType))
{
if(( pLValue->val.iVal > 0) && ( pRValue->val.iVal < 0))
{
pResult->val.uiVal = (FLMUINT)(pLValue->val.iVal - pRValue->val.iVal);
pResult->eValType = XFLM_UINT_VAL;
}
else
{
pResult->val.iVal = pLValue->val.iVal - pRValue->val.iVal;
pResult->eValType = (pResult->val.iVal < 0)
? XFLM_INT_VAL : XFLM_UINT_VAL;
}
}
else
{
FLMINT64 i64LValue = fqGetInt64( pLValue);
FLMINT64 i64RValue = fqGetInt64( pRValue);
if( (i64LValue > 0) && (i64RValue < 0))
{
pResult->val.ui64Val = (FLMUINT64)( i64LValue - i64RValue);
pResult->eValType = XFLM_UINT64_VAL;
}
else
{
pResult->val.i64Val = i64LValue - i64RValue;
pResult->eValType = (pResult->val.i64Val < 0)
? XFLM_INT64_VAL : XFLM_UINT64_VAL;
}
}
}
/***************************************************************************
Desc: Performs a subtraction operation
***************************************************************************/
FSTATIC void fqOpSUMinus(
FQVALUE * pLValue,
FQVALUE * pRValue,
FQVALUE * pResult)
{
if( isNativeNum( pLValue->eValType) &&
isNativeNum( pRValue->eValType))
{
if( pRValue->val.uiVal > gv_uiMaxSignedIntVal)
{
pResult->val.iVal = (pLValue->val.iVal - gv_uiMaxSignedIntVal) -
(FLMINT)(pRValue->val.uiVal - gv_uiMaxSignedIntVal);
pResult->eValType = XFLM_INT_VAL;
}
else
{
pResult->val.iVal = pLValue->val.iVal - (FLMINT)pRValue->val.uiVal;
pResult->eValType = (pResult->val.iVal < 0)
? XFLM_INT_VAL : XFLM_UINT_VAL;
}
}
else
{
FLMINT64 i64LValue = fqGetInt64( pLValue);
FLMUINT64 ui64RValue = fqGetUInt64( pRValue);
if( ui64RValue > gv_ui64MaxSignedIntVal)
{
pResult->val.i64Val = (i64LValue - gv_ui64MaxSignedIntVal) -
(FLMINT64)(ui64RValue - gv_ui64MaxSignedIntVal);
pResult->eValType = XFLM_INT64_VAL;
}
else
{
pResult->val.i64Val = i64LValue - (FLMINT64)ui64RValue;
pResult->eValType = (pResult->val.i64Val < 0)
? XFLM_INT64_VAL : XFLM_UINT64_VAL;
}
}
}
/***************************************************************************
Desc: Compare two entire strings.
****************************************************************************/
RCODE fqCompareCollStreams(
F_CollIStream * pLStream,
F_CollIStream * pRStream,
FLMBOOL bOpIsMatch,
FLMUINT uiLanguage,
FLMINT * piResult)
{
RCODE rc = NE_XFLM_OK;
FLMUINT16 ui16RCol;
FLMUINT16 ui16LCol;
FLMUINT16 ui16RSubCol;
FLMUINT16 ui16LSubCol;
FLMBYTE ucRCase;
FLMBYTE ucLCase;
F_CollStreamPos savedRPos;
F_CollStreamPos savedLPos;
F_CollStreamPos startLPos;
FLMUNICODE uLChar = 0;
FLMBOOL bLCharIsWild = FALSE;
FLMUNICODE uRChar = 0;
FLMBOOL bRCharIsWild = FALSE;
FLMBOOL bPrevLWasWild = FALSE;
FLMBOOL bPrevRWasWild = FALSE;
FLMBOOL bAllowTwoIntoOne;
// If we are doing a "match" operation, we don't want two
// character sequences like Ch, ae, etc. turned into a single
// a single collation, because then matches that involve wildcards
// like "aetna == a*" would not match properly.
// When not doing a match operation, we WANT two character sequences
// turned into a single collation value so that we can know if
// something is > or <. When doing match operations, all we care
// about is if they are equal or not, so there is no need to look
// at double character collation properties.
bAllowTwoIntoOne = bOpIsMatch ? FALSE : TRUE;
for( ;;)
{
GetNextLChar:
if( bLCharIsWild)
{
bPrevLWasWild = TRUE;
}
pLStream->getCurrPosition( &startLPos);
if( RC_BAD( rc = pLStream->read(
bAllowTwoIntoOne,
&uLChar, &bLCharIsWild, &ui16LCol, &ui16LSubCol, &ucLCase)))
{
if( rc == NE_XFLM_EOF_HIT)
{
rc = NE_XFLM_OK;
// If the last character was a wildcard, we have a match!
if( bPrevLWasWild)
{
*piResult = 0;
goto Exit;
}
for( ;;)
{
if( RC_BAD( rc = pRStream->read(
bAllowTwoIntoOne,
&uRChar, &bRCharIsWild, &ui16RCol, &ui16RSubCol, &ucRCase)))
{
if( rc == NE_XFLM_EOF_HIT)
{
rc = NE_XFLM_OK;
*piResult = 0;
}
goto Exit;
}
// Break out when we hit a non-wild character
if( !bRCharIsWild)
{
break;
}
}
*piResult = -1;
}
goto Exit;
}
if( bLCharIsWild)
{
// Consume multiple wildcards
if( bPrevLWasWild)
{
goto GetNextLChar;
}
// See if we match anywhere on the remaining right string
for( ;;)
{
pRStream->getCurrPosition( &savedRPos);
pLStream->getCurrPosition( &savedLPos);
if( RC_BAD( rc = fqCompareCollStreams( pLStream, pRStream,
bOpIsMatch, uiLanguage, piResult)))
{
goto Exit;
}
if( !(*piResult))
{
goto Exit;
}
if( RC_BAD( rc = pRStream->positionTo( &savedRPos)))
{
goto Exit;
}
if( RC_BAD( rc = pRStream->read(
bAllowTwoIntoOne,
NULL, NULL, NULL, NULL, NULL)))
{
if( rc == NE_XFLM_EOF_HIT)
{
rc = NE_XFLM_OK;
break;
}
goto Exit;
}
if( RC_BAD( rc = pLStream->positionTo( &savedLPos)))
{
goto Exit;
}
}
*piResult = 1;
goto Exit;
}
GetNextRChar:
if( bRCharIsWild)
{
bPrevRWasWild = TRUE;
}
if( RC_BAD( rc = pRStream->read(
bAllowTwoIntoOne,
&uRChar, &bRCharIsWild, &ui16RCol, &ui16RSubCol, &ucRCase)))
{
if( rc == NE_XFLM_EOF_HIT)
{
rc = NE_XFLM_OK;
// If the last character was a wildcard, we have a match!
if( bPrevRWasWild)
{
*piResult = 0;
}
else
{
*piResult = 1;
}
}
goto Exit;
}
if( bRCharIsWild)
{
if( bPrevRWasWild)
{
goto GetNextRChar;
}
// See if we match anywhere on the remaining left string
if( RC_BAD( rc = pLStream->positionTo( &startLPos)))
{
goto Exit;
}
for( ;;)
{
pLStream->getCurrPosition( &savedLPos);
pRStream->getCurrPosition( &savedRPos);
if( RC_BAD( rc = fqCompareCollStreams( pLStream, pRStream,
bOpIsMatch, uiLanguage, piResult)))
{
goto Exit;
}
if( !(*piResult))
{
goto Exit;
}
if( RC_BAD( rc = pRStream->positionTo( &savedRPos)))
{
goto Exit;
}
if( RC_BAD( rc = pLStream->positionTo( &savedLPos)))
{
goto Exit;
}
// Skip the character we just processed
if( RC_BAD( rc = pLStream->read(
bAllowTwoIntoOne,
NULL, NULL, NULL, NULL, NULL)))
{
if( rc == NE_XFLM_EOF_HIT)
{
rc = NE_XFLM_OK;
break;
}
goto Exit;
}
}
*piResult = -1;
goto Exit;
}
if( ui16LCol != ui16RCol)
{
*piResult = ui16LCol < ui16RCol ? -1 : 1;
goto Exit;
}
else if( ui16LSubCol != ui16RSubCol)
{
*piResult = ui16LSubCol < ui16RSubCol ? -1 : 1;
goto Exit;
}
else if( ucLCase != ucRCase)
{
// NOTE: If we are doing a case insensitive comparison,
// ucLCase and ucRCase should be equal (both will have been
// set to zero
*piResult = ucLCase < ucRCase ? -1 : 1;
goto Exit;
}
}
Exit:
return( rc);
}
/***************************************************************************
Desc: Compare two entire strings.
****************************************************************************/
FSTATIC RCODE fqCompareText(
IF_OperandComparer * pOpComparer,
FQVALUE * pLValue,
FQVALUE * pRValue,
FLMUINT uiCompareRules,
FLMBOOL bOpIsMatch,
FLMUINT uiLanguage,
FLMINT * piResult)
{
RCODE rc = NE_XFLM_OK;
F_BufferIStream bufferLStream;
IF_PosIStream * pLStream;
F_BufferIStream bufferRStream;
IF_PosIStream * pRStream;
F_CollIStream lStream;
F_CollIStream rStream;
// Types must be text
if (pLValue->eValType != XFLM_UTF8_VAL ||
pRValue->eValType != XFLM_UTF8_VAL)
{
rc = RC_SET_AND_ASSERT( NE_XFLM_NOT_IMPLEMENTED);
goto Exit;
}
// Open the streams
if( !(pLValue->uiFlags & VAL_IS_STREAM))
{
if (RC_BAD( rc = bufferLStream.open( pLValue->val.pucBuf,
pLValue->uiDataLen)))
{
goto Exit;
}
pLStream = &bufferLStream;
}
else
{
pLStream = pLValue->val.pIStream;
}
if( !(pRValue->uiFlags & VAL_IS_STREAM))
{
if( RC_BAD( rc = bufferRStream.open( pRValue->val.pucBuf,
pRValue->uiDataLen)))
{
goto Exit;
}
pRStream = &bufferRStream;
}
else
{
pRStream = pRValue->val.pIStream;
}
if (pOpComparer)
{
rc = pOpComparer->compare( pLStream, pRStream, piResult);
goto Exit;
}
// Open up the collated streams
if (RC_BAD( rc = lStream.open( pLStream, FALSE, uiLanguage, uiCompareRules,
(bOpIsMatch && (pLValue->uiFlags & VAL_IS_CONSTANT)) ? TRUE : FALSE)))
{
goto Exit;
}
if (RC_BAD( rc = rStream.open( pRStream, FALSE, uiLanguage, uiCompareRules,
(bOpIsMatch && (pRValue->uiFlags & VAL_IS_CONSTANT)) ? TRUE : FALSE)))
{
goto Exit;
}
if (RC_BAD( rc = fqCompareCollStreams( &lStream, &rStream,
bOpIsMatch, uiLanguage, piResult)))
{
goto Exit;
}
Exit:
return( rc);
}
/***************************************************************************
Desc: Approximate compare - only works for strings right now.
****************************************************************************/
FSTATIC RCODE fqApproxCompare(
FQVALUE * pLValue,
FQVALUE * pRValue,
FLMINT * piResult)
{
RCODE rc = NE_XFLM_OK;
FLMUINT uiLMeta;
FLMUINT uiRMeta;
FLMUINT64 ui64StartPos;
F_BufferIStream bufferLStream;
IF_PosIStream * pLStream;
F_BufferIStream bufferRStream;
IF_PosIStream * pRStream;
// Types must be text
if (pLValue->eValType != XFLM_UTF8_VAL ||
pRValue->eValType != XFLM_UTF8_VAL)
{
rc = RC_SET_AND_ASSERT( NE_XFLM_NOT_IMPLEMENTED);
goto Exit;
}
// Open the streams
if (!(pLValue->uiFlags & VAL_IS_STREAM))
{
if (RC_BAD( rc = bufferLStream.open( pLValue->val.pucBuf,
pLValue->uiDataLen)))
{
goto Exit;
}
pLStream = &bufferLStream;
}
else
{
pLStream = pLValue->val.pIStream;
}
if (!(pRValue->uiFlags & VAL_IS_STREAM))
{
if( RC_BAD( rc = bufferRStream.open( pRValue->val.pucBuf,
pRValue->uiDataLen)))
{
goto Exit;
}
pRStream = &bufferRStream;
}
else
{
pRStream = pRValue->val.pIStream;
}
if ((pLValue->uiFlags & VAL_IS_CONSTANT) ||
!(pRValue->uiFlags & VAL_IS_CONSTANT))
{
for( ;;)
{
if( RC_BAD( rc = flmGetNextMetaphone( pLStream, &uiLMeta)))
{
if( rc == NE_XFLM_EOF_HIT)
{
*piResult = 0;
rc = NE_XFLM_OK;
}
goto Exit;
}
ui64StartPos = pRStream->getCurrPosition();
for( ;;)
{
if( RC_BAD( rc = flmGetNextMetaphone( pRStream, &uiRMeta)))
{
if( rc == NE_XFLM_EOF_HIT)
{
rc = NE_XFLM_OK;
*piResult = -1;
}
goto Exit;
}
if( uiLMeta == uiRMeta)
{
break;
}
}
if( RC_BAD( rc = pRStream->positionTo( ui64StartPos)))
{
goto Exit;
}
}
}
else
{
for( ;;)
{
if( RC_BAD( rc = flmGetNextMetaphone( pRStream, &uiRMeta)))
{
if( rc == NE_XFLM_EOF_HIT)
{
*piResult = 0;
rc = NE_XFLM_OK;
}
goto Exit;
}
ui64StartPos = pLStream->getCurrPosition();
for( ;;)
{
if( RC_BAD( rc = flmGetNextMetaphone( pLStream, &uiLMeta)))
{
if( rc == NE_XFLM_EOF_HIT)
{
rc = NE_XFLM_OK;
*piResult = 1;
}
goto Exit;
}
if( uiLMeta == uiRMeta)
{
break;
}
}
if( RC_BAD( rc = pLStream->positionTo( ui64StartPos)))
{
goto Exit;
}
}
}
Exit:
return( rc);
}
/***************************************************************************
Desc: Performs binary comparison on two streams - may be text or binary,
it really doesn't matter. Returns XFLM_TRUE or XFLM_FALSE.
***************************************************************************/
FSTATIC RCODE fqCompareBinary(
IF_OperandComparer * pOpComparer,
FQVALUE * pLValue,
FQVALUE * pRValue,
FLMINT * piResult)
{
RCODE rc = NE_XFLM_OK;
F_BufferIStream bufferLStream;
IF_PosIStream * pLStream;
F_BufferIStream bufferRStream;
IF_PosIStream * pRStream;
FLMBYTE ucLByte;
FLMBYTE ucRByte;
FLMUINT uiOffset = 0;
FLMBOOL bLEmpty = FALSE;
*piResult = 0;
// Types must be binary
if ( pLValue->eValType != XFLM_BINARY_VAL ||
pRValue->eValType != XFLM_BINARY_VAL)
{
rc = RC_SET_AND_ASSERT( NE_XFLM_NOT_IMPLEMENTED);
goto Exit;
}
// Open the streams
if( !(pLValue->uiFlags & VAL_IS_STREAM))
{
if (RC_BAD( rc = bufferLStream.open( pLValue->val.pucBuf,
pLValue->uiDataLen)))
{
goto Exit;
}
pLStream = &bufferLStream;
}
else
{
pLStream = pLValue->val.pIStream;
}
if( !(pRValue->uiFlags & VAL_IS_STREAM))
{
if( RC_BAD( rc = bufferRStream.open( pRValue->val.pucBuf,
pRValue->uiDataLen)))
{
goto Exit;
}
pRStream = &bufferRStream;
}
else
{
pRStream = pRValue->val.pIStream;
}
if (pOpComparer)
{
rc = pOpComparer->compare( pLStream, pRStream, piResult);
goto Exit;
}
for (;;)
{
if (RC_BAD( rc = flmReadStorageAsBinary(
pLStream, &ucLByte, 1, uiOffset, NULL)))
{
if (rc == NE_XFLM_EOF_HIT)
{
rc = NE_XFLM_OK;
bLEmpty = TRUE;
}
else
{
goto Exit;
}
}
if (RC_BAD( rc = flmReadStorageAsBinary(
pRStream, &ucRByte, 1, uiOffset, NULL)))
{
if (rc == NE_XFLM_EOF_HIT)
{
rc = NE_XFLM_OK;
if( bLEmpty)
{
*piResult = 0;
}
else
{
*piResult = 1;
}
}
goto Exit;
}
else if( bLEmpty)
{
*piResult = -1;
goto Exit;
}
if( ucLByte != ucRByte)
{
*piResult = ucLByte < ucRByte ? -1 : 1;
goto Exit;
}
uiOffset++;
}
Exit:
return( rc);
}
/***************************************************************************
Desc: Compare two values. This routine assumes that pValue1 and pValue2
are non-null.
***************************************************************************/
RCODE fqCompare(
FQVALUE * pValue1,
FQVALUE * pValue2,
FLMUINT uiCompareRules,
IF_OperandComparer * pOpComparer,
FLMUINT uiLanguage,
FLMINT * piCmp)
{
RCODE rc = NE_XFLM_OK;
// We have already called fqCanCompare, so no need to do it here
switch (pValue1->eValType)
{
case XFLM_BOOL_VAL:
*piCmp = pValue1->val.eBool > pValue2->val.eBool
? 1
: pValue1->val.eBool < pValue2->val.eBool
? -1
: 0;
break;
case XFLM_UINT_VAL:
switch (pValue2->eValType)
{
case XFLM_UINT_VAL:
*piCmp = pValue1->val.uiVal > pValue2->val.uiVal
? 1
: pValue1->val.uiVal < pValue2->val.uiVal
? -1
: 0;
break;
case XFLM_UINT64_VAL:
*piCmp = (FLMUINT64)pValue1->val.uiVal > pValue2->val.ui64Val
? 1
: (FLMUINT64)pValue1->val.uiVal < pValue2->val.ui64Val
? -1
: 0;
break;
case XFLM_INT_VAL:
*piCmp = pValue2->val.iVal < 0 ||
pValue1->val.uiVal > (FLMUINT)pValue2->val.iVal
? 1
: pValue1->val.uiVal < (FLMUINT)pValue2->val.iVal
? -1
: 0;
break;
case XFLM_INT64_VAL:
*piCmp = pValue2->val.i64Val < 0 ||
(FLMUINT64)pValue1->val.uiVal >
(FLMUINT64)pValue2->val.i64Val
? 1
: (FLMUINT64)pValue1->val.uiVal <
(FLMUINT64)pValue2->val.i64Val
? -1
: 0;
break;
default:
rc = RC_SET_AND_ASSERT( NE_XFLM_NOT_IMPLEMENTED);
goto Exit;
}
break;
case XFLM_UINT64_VAL:
switch (pValue2->eValType)
{
case XFLM_UINT_VAL:
*piCmp = pValue1->val.ui64Val > (FLMUINT64)pValue2->val.uiVal
? 1
: pValue1->val.ui64Val < (FLMUINT64)pValue2->val.uiVal
? -1
: 0;
break;
case XFLM_UINT64_VAL:
*piCmp = pValue1->val.ui64Val > pValue2->val.ui64Val
? 1
: pValue1->val.ui64Val < pValue2->val.ui64Val
? -1
: 0;
break;
case XFLM_INT_VAL:
*piCmp = pValue2->val.iVal < 0 ||
pValue1->val.ui64Val > (FLMUINT64)pValue2->val.iVal
? 1
: pValue1->val.ui64Val < (FLMUINT64)pValue2->val.iVal
? -1
: 0;
break;
case XFLM_INT64_VAL:
*piCmp = pValue2->val.i64Val < 0 ||
pValue1->val.ui64Val > (FLMUINT64)pValue2->val.i64Val
? 1
: pValue1->val.ui64Val < (FLMUINT64)pValue2->val.i64Val
? -1
: 0;
break;
default:
rc = RC_SET_AND_ASSERT( NE_XFLM_NOT_IMPLEMENTED);
goto Exit;
}
break;
case XFLM_INT_VAL:
switch (pValue2->eValType)
{
case XFLM_UINT_VAL:
*piCmp = pValue1->val.iVal < 0 ||
(FLMUINT)pValue1->val.iVal < pValue2->val.uiVal
? -1
: (FLMUINT)pValue1->val.iVal > pValue2->val.uiVal
? 1
: 0;
break;
case XFLM_UINT64_VAL:
*piCmp = pValue1->val.iVal < 0 ||
(FLMUINT64)pValue1->val.iVal < pValue2->val.ui64Val
? -1
: (FLMUINT64)pValue1->val.iVal > pValue2->val.ui64Val
? 1
: 0;
break;
case XFLM_INT_VAL:
*piCmp = pValue1->val.iVal < pValue2->val.iVal
? -1
: pValue1->val.iVal > pValue2->val.iVal
? 1
: 0;
break;
case XFLM_INT64_VAL:
*piCmp = (FLMINT64)pValue1->val.iVal < pValue2->val.i64Val
? -1
: (FLMINT64)pValue1->val.iVal > pValue2->val.i64Val
? 1
: 0;
break;
default:
rc = RC_SET_AND_ASSERT( NE_XFLM_NOT_IMPLEMENTED);
goto Exit;
}
break;
case XFLM_INT64_VAL:
switch (pValue2->eValType)
{
case XFLM_UINT_VAL:
*piCmp = pValue1->val.i64Val < 0 ||
(FLMUINT64)pValue1->val.i64Val <
(FLMUINT64)pValue2->val.uiVal
? -1
: (FLMUINT64)pValue1->val.i64Val >
(FLMUINT64)pValue2->val.uiVal
? 1
: 0;
break;
case XFLM_UINT64_VAL:
*piCmp = pValue1->val.i64Val < 0 ||
(FLMUINT64)pValue1->val.i64Val < pValue2->val.ui64Val
? -1
: (FLMUINT64)pValue1->val.i64Val > pValue2->val.ui64Val
? 1
: 0;
break;
case XFLM_INT_VAL:
*piCmp = pValue1->val.i64Val < (FLMINT64)pValue2->val.iVal
? -1
: pValue1->val.i64Val > (FLMINT64)pValue2->val.iVal
? 1
: 0;
break;
case XFLM_INT64_VAL:
*piCmp = pValue1->val.i64Val < pValue2->val.i64Val
? -1
: pValue1->val.i64Val > pValue2->val.i64Val
? 1
: 0;
break;
default:
rc = RC_SET_AND_ASSERT( NE_XFLM_NOT_IMPLEMENTED);
goto Exit;
}
break;
case XFLM_BINARY_VAL:
if (RC_BAD( rc = fqCompareBinary( pOpComparer, pValue1,
pValue2, piCmp)))
{
goto Exit;
}
break;
case XFLM_UTF8_VAL:
if (RC_BAD( rc = fqCompareText( pOpComparer,
pValue1, pValue2,
uiCompareRules, FALSE, uiLanguage, piCmp)))
{
goto Exit;
}
break;
default:
break;
}
Exit:
return( rc);
}
/***************************************************************************
Desc: Do a comparison operator.
***************************************************************************/
RCODE fqCompareOperands(
FLMUINT uiLanguage,
FQVALUE * pLValue,
FQVALUE * pRValue,
eQueryOperators eOperator,
FLMUINT uiCompareRules,
IF_OperandComparer * pOpComparer,
FLMBOOL bNotted,
XFlmBoolType * peBool)
{
RCODE rc = NE_XFLM_OK;
FLMINT iCmp;
if (!pLValue || pLValue->eValType == XFLM_MISSING_VAL ||
!pRValue || pRValue->eValType == XFLM_MISSING_VAL ||
!fqCanCompare( pLValue, pRValue))
{
*peBool = (bNotted ? XFLM_TRUE : XFLM_FALSE);
}
// At this point, both operands are known to be present and are of
// types that can be compared. The comparison
// will therefore be performed according to the
// operator specified.
else
{
switch (eOperator)
{
case XFLM_EQ_OP:
case XFLM_NE_OP:
if (pLValue->eValType == XFLM_UTF8_VAL ||
pRValue->eValType == XFLM_UTF8_VAL)
{
if (RC_BAD( rc = fqCompareText( pOpComparer, pLValue, pRValue,
uiCompareRules, TRUE, uiLanguage, &iCmp)))
{
goto Exit;
}
}
else
{
if (RC_BAD( rc = fqCompare( pLValue, pRValue,
uiCompareRules, pOpComparer, uiLanguage, &iCmp)))
{
goto Exit;
}
}
if (eOperator == XFLM_EQ_OP)
{
*peBool = (iCmp == 0 ? XFLM_TRUE : XFLM_FALSE);
}
else
{
*peBool = (iCmp != 0 ? XFLM_TRUE : XFLM_FALSE);
}
break;
case XFLM_APPROX_EQ_OP:
if (RC_BAD( rc = fqApproxCompare( pLValue, pRValue, &iCmp)))
{
goto Exit;
}
*peBool = (iCmp == 0 ? XFLM_TRUE : XFLM_FALSE);
break;
case XFLM_LT_OP:
if (RC_BAD( rc = fqCompare( pLValue, pRValue,
uiCompareRules, pOpComparer, uiLanguage, &iCmp)))
{
goto Exit;
}
*peBool = (iCmp < 0 ? XFLM_TRUE : XFLM_FALSE);
break;
case XFLM_LE_OP:
if (RC_BAD( rc = fqCompare( pLValue, pRValue,
uiCompareRules, pOpComparer, uiLanguage, &iCmp)))
{
goto Exit;
}
*peBool = (iCmp <= 0 ? XFLM_TRUE : XFLM_FALSE);
break;
case XFLM_GT_OP:
if (RC_BAD( rc = fqCompare( pLValue, pRValue,
uiCompareRules, pOpComparer, uiLanguage, &iCmp)))
{
goto Exit;
}
*peBool = (iCmp > 0 ? XFLM_TRUE : XFLM_FALSE);
break;
case XFLM_GE_OP:
if (RC_BAD( rc = fqCompare( pLValue, pRValue,
uiCompareRules, pOpComparer, uiLanguage, &iCmp)))
{
goto Exit;
}
*peBool = (iCmp >= 0 ? XFLM_TRUE : XFLM_FALSE);
break;
default:
*peBool = XFLM_UNKNOWN;
rc = RC_SET_AND_ASSERT( NE_XFLM_QUERY_SYNTAX);
goto Exit;
}
}
Exit:
return( rc);
}
/***************************************************************************
Desc: Do an arithmetic operator.
***************************************************************************/
RCODE fqArithmeticOperator(
FQVALUE * pLValue,
FQVALUE * pRValue,
eQueryOperators eOperator,
FQVALUE * pResult)
{
RCODE rc = NE_XFLM_OK;
FQ_OPERATION * fnOp;
FLMUINT uiOffset = 0;
if( !isArithOp( eOperator))
{
rc = RC_SET( NE_XFLM_SYNTAX);
goto Exit;
}
if (pLValue->eValType == XFLM_MISSING_VAL ||
pRValue->eValType == XFLM_MISSING_VAL)
{
pResult->eValType = XFLM_MISSING_VAL;
goto Exit;
}
if( isUnsigned( pLValue))
{
if( isUnsigned( pRValue))
{
uiOffset = 0;
}
else if( isSigned( pRValue))
{
uiOffset = 1;
}
else
{
rc = RC_SET_AND_ASSERT( NE_XFLM_NOT_IMPLEMENTED);
goto Exit;
}
}
else if( isSigned( pLValue))
{
if( isUnsigned( pRValue))
{
uiOffset = 2;
}
else if( isSigned( pRValue))
{
uiOffset = 3;
}
else
{
rc = RC_SET_AND_ASSERT( NE_XFLM_NOT_IMPLEMENTED);
goto Exit;
}
}
fnOp = FQ_ArithOpTable[ ((((FLMUINT)eOperator) -
XFLM_FIRST_ARITH_OP) * 4) + uiOffset];
fnOp( pLValue, pRValue, pResult);
Exit:
return( rc);
}
/*****************************************************************************
Desc:
******************************************************************************/
RCODE F_CollIStream::read(
FLMBOOL bAllowTwoIntoOne,
FLMUNICODE * puChar,
FLMBOOL * pbCharIsWild,
FLMUINT16 * pui16Col,
FLMUINT16 * pui16SubCol,
FLMBYTE * pucCase)
{
RCODE rc = NE_XFLM_OK;
FLMUNICODE uChar;
FLMUINT16 ui16WpChar;
FLMUINT16 ui16NextWpChar;
FLMUINT16 ui16Col;
FLMUINT16 ui16SubCol;
FLMBOOL bTwoIntoOne;
FLMBYTE ucCase;
FLMBOOL bAsian;
FLMBOOL bLastCharWasSpace = FALSE;
FLMUINT64 ui64AfterLastSpacePos = 0;
FLMUINT64 ui64CurrCharPos = 0;
if (pbCharIsWild)
{
*pbCharIsWild = FALSE;
}
// Is this a double-byte (Asian) character set?
bAsian = (m_uiLanguage >= FIRST_DBCS_LANG && m_uiLanguage <= LAST_DBCS_LANG)
? TRUE
: FALSE;
// Get the next character from the stream
GetNextChar:
ui16WpChar = 0;
ui16NextWpChar = 0;
ui16Col = 0;
ui16SubCol = 0;
bTwoIntoOne = FALSE;
ucCase = 0;
if (m_uNextChar)
{
uChar = m_uNextChar;
m_uNextChar = 0;
}
else
{
ui64CurrCharPos = m_pIStream->getCurrPosition();
if( RC_BAD( rc = readCharFromStream( &uChar)))
{
if (rc != NE_XFLM_EOF_HIT)
{
goto Exit;
}
// If we were skipping spaces, we need to
// process a single space character, unless we are
// ignoring trailing white space.
if (bLastCharWasSpace &&
!(m_uiCompareRules & XFLM_COMP_IGNORE_TRAILING_SPACE))
{
// bLastCharWasSpace flag can only be TRUE if either
// XFLM_COMP_IGNORE_TRAILING_SPACE is set or
// XFLM_COMP_COMPRESS_WHITESPACE is set.
flmAssert( m_uiCompareRules & XFLM_COMP_COMPRESS_WHITESPACE);
uChar = ASCII_SPACE;
rc = NE_XFLM_OK;
goto Process_Char;
}
goto Exit;
}
}
if ((uChar = flmConvertChar( uChar, m_uiCompareRules)) == 0)
{
goto GetNextChar;
}
// Deal with spaces
if (uChar == ASCII_SPACE)
{
if (m_uiCompareRules & XFLM_COMP_COMPRESS_WHITESPACE)
{
bLastCharWasSpace = TRUE;
ui64AfterLastSpacePos = m_pIStream->getCurrPosition();
goto GetNextChar;
}
else if (m_uiCompareRules & XFLM_COMP_IGNORE_TRAILING_SPACE)
{
if (!bLastCharWasSpace)
{
bLastCharWasSpace = TRUE;
// Save where we are at so that if this doesn't turn out
// to be trailing spaces, we can restore this position.
ui64AfterLastSpacePos = m_pIStream->getCurrPosition();
}
goto GetNextChar;
}
}
else
{
if (m_uiCompareRules & XFLM_COMP_IGNORE_LEADING_SPACE)
{
m_ui64EndOfLeadingSpacesPos = ui64CurrCharPos;
m_uiCompareRules &= (~(XFLM_COMP_IGNORE_LEADING_SPACE));
}
// If the last character was a space, we need to process it.
if (bLastCharWasSpace)
{
// Position back to after the last space, and process a space
// character.
if (RC_BAD( rc = m_pIStream->positionTo( ui64AfterLastSpacePos)))
{
goto Exit;
}
uChar = ASCII_SPACE;
bLastCharWasSpace = FALSE;
}
else if (uChar == ASCII_BACKSLASH)
{
// If wildcards are allowed, the backslash should be treated
// as an escape character, and the next character is the one
// we want. Otherwise, it should be treated as
// the actual character we want returned.
if (m_bMayHaveWildCards)
{
// Got a backslash. Means the next character is to be taken
// no matter what because it is escaped.
if (RC_BAD( rc = readCharFromStream( &uChar)))
{
if (rc != NE_XFLM_EOF_HIT)
{
goto Exit;
}
rc = NE_XFLM_OK;
uChar = ASCII_BACKSLASH;
}
}
}
else if (uChar == ASCII_WILDCARD)
{
if (m_bMayHaveWildCards && pbCharIsWild)
{
*pbCharIsWild = TRUE;
}
}
}
Process_Char:
if (!bAsian)
{
// Must check for double characters if non-US and non-Asian
// character set
if (m_uiLanguage != XFLM_US_LANG)
{
if (RC_BAD( rc = flmWPCheckDoubleCollation(
m_pIStream, m_bUnicodeStream, bAllowTwoIntoOne,
&uChar, &m_uNextChar, &bTwoIntoOne, m_uiLanguage)))
{
goto Exit;
}
}
}
else
{
if (RC_BAD( rc = readCharFromStream( &m_uNextChar)))
{
if (rc == NE_XFLM_EOF_HIT)
{
rc = NE_XFLM_OK;
m_uNextChar = 0;
}
else
{
RC_UNEXPECTED_ASSERT( rc);
goto Exit;
}
}
}
// Convert each character to its WP equivalent
if (!flmUnicodeToWP( uChar, &ui16WpChar))
{
ui16WpChar = 0;
}
if (!flmUnicodeToWP( m_uNextChar, &ui16NextWpChar))
{
ui16NextWpChar = 0;
}
// If we have an unconvertible UNICODE character, the collation
// value for it will be COLS0
if (!ui16WpChar)
{
if (!bAsian)
{
ui16Col = COLS0;
}
else
{
if (uChar < 0x20)
{
ui16Col = 0xFFFF;
ui16SubCol = uChar;
}
else
{
ui16Col = uChar;
ui16SubCol = 0;
}
}
}
else
{
if (!bAsian)
{
ui16Col = flmWPGetCollation( ui16WpChar, m_uiLanguage);
if (bTwoIntoOne)
{
// Since two characters were merged into one, increment
// the collation value by one. In the case of something
// like 'ch', there is a collation value between 'c' and
// 'd'. flmWPGetCollation would have returned the
// collation value for 'c' ... incrementing by one gives
// us the proper collation value for 'ch' (i.e., the
// collation value between 'c' and 'd').
ui16Col++;
}
}
else
{
if (flmWPAsiaGetCollation( ui16WpChar, ui16NextWpChar, ui16Col,
&ui16Col, &ui16SubCol, &ucCase, !m_bCaseSensitive) == 2)
{
// Next character was consumed by collation
m_uNextChar = 0;
}
}
}
if (pui16Col)
{
*pui16Col = ui16Col;
}
// Consume m_uNextChar if two characters merged into one
if (bTwoIntoOne)
{
m_uNextChar = 0;
}
// Subcollation
if( pui16SubCol)
{
if( uChar > 127 && !bAsian)
{
ui16SubCol = ui16WpChar
? flmWPGetSubCol( ui16WpChar, ui16Col, m_uiLanguage)
: uChar;
if( !m_bCaseSensitive)
{
// If the sub-collation value is the original
// character, it means that the collation could not
// distinguish the characters and sub-collation is being
// used to do it. However, this creates a problem when the
// characters are the same character except for case. In that
// scenario, we incorrectly return a not-equal when we are
// doing a case-insensitive comparison. So, at this point,
// we need to use the sub-collation for the upper-case of the
// character instead of the sub-collation for the character
// itself.
if( ui16WpChar && ui16SubCol == ui16WpChar)
{
ui16SubCol = flmWPGetSubCol(
flmWPUpper( ui16WpChar),
ui16Col, m_uiLanguage);
}
}
}
*pui16SubCol = ui16SubCol;
}
// Case
if( pucCase)
{
if (!m_bCaseSensitive)
{
*pucCase = 0;
}
else
{
if (!bAsian && ui16WpChar)
{
// flmWPIsUpper() returns FALSE if the character is lower or
// TRUE if the character is not lower case.
if( flmWPIsUpper( ui16WpChar))
{
if( bTwoIntoOne)
{
if( flmWPIsUpper( ui16NextWpChar))
{
ucCase = 0x03;
}
else
{
ucCase = 0x10;
}
}
else
{
ucCase = 0x01;
}
}
}
*pucCase = ucCase;
}
}
if (puChar)
{
*puChar = uChar;
}
Exit:
return( rc);
}
/***************************************************************************
Desc:
****************************************************************************/
RCODE F_DbSystem::compareUTF8Strings(
const FLMBYTE * pucLString,
FLMUINT uiLStrBytes,
FLMBOOL bLeftWild,
const FLMBYTE * pucRString,
FLMUINT uiRStrBytes,
FLMBOOL bRightWild,
FLMUINT uiCompareRules,
FLMUINT uiLanguage,
FLMINT * piResult)
{
RCODE rc = NE_XFLM_OK;
F_BufferIStream bufferLStream;
F_BufferIStream bufferRStream;
F_CollIStream lStream;
F_CollIStream rStream;
if (RC_BAD( rc = bufferLStream.open( pucLString, uiLStrBytes)))
{
goto Exit;
}
if( RC_BAD( rc = bufferRStream.open( pucRString, uiRStrBytes)))
{
goto Exit;
}
if( RC_BAD( rc = lStream.open( &bufferLStream, FALSE, uiLanguage,
uiCompareRules, bLeftWild)))
{
goto Exit;
}
if( RC_BAD( rc = rStream.open( &bufferRStream, FALSE, uiLanguage,
uiCompareRules, bRightWild)))
{
goto Exit;
}
if( RC_BAD( rc = fqCompareCollStreams( &lStream, &rStream,
(bLeftWild || bRightWild) ? TRUE : FALSE,
uiLanguage, piResult)))
{
goto Exit;
}
Exit:
return( rc);
}
/***************************************************************************
Desc:
****************************************************************************/
RCODE F_DbSystem::compareUnicodeStrings(
const FLMUNICODE * puzLString,
FLMUINT uiLStrBytes,
FLMBOOL bLeftWild,
const FLMUNICODE * puzRString,
FLMUINT uiRStrBytes,
FLMBOOL bRightWild,
FLMUINT uiCompareRules,
FLMUINT uiLanguage,
FLMINT * piResult)
{
RCODE rc = NE_XFLM_OK;
F_BufferIStream bufferLStream;
F_BufferIStream bufferRStream;
F_CollIStream lStream;
F_CollIStream rStream;
if( RC_BAD( rc = bufferLStream.open( (FLMBYTE *)puzLString, uiLStrBytes)))
{
goto Exit;
}
if( RC_BAD( rc = bufferRStream.open( (FLMBYTE *)puzRString, uiRStrBytes)))
{
goto Exit;
}
if( RC_BAD( rc = lStream.open( &bufferLStream, TRUE, uiLanguage,
uiCompareRules, bLeftWild)))
{
goto Exit;
}
if( RC_BAD( rc = rStream.open( &bufferRStream, TRUE, uiLanguage,
uiCompareRules, bRightWild)))
{
goto Exit;
}
if( RC_BAD( rc = fqCompareCollStreams( &lStream, &rStream,
(bLeftWild || bRightWild) ? TRUE : FALSE, uiLanguage, piResult)))
{
goto Exit;
}
Exit:
return( rc);
}
/***************************************************************************
Desc:
****************************************************************************/
RCODE XFLMAPI F_DbSystem::utf8IsSubStr(
const FLMBYTE * pszString,
const FLMBYTE * pszSubString,
FLMUINT uiCompareRules,
FLMUINT uiLanguage,
FLMBOOL * pbExists)
{
RCODE rc = NE_XFLM_OK;
FLMINT iResult = 0;
FLMBYTE * pszSearch = NULL;
FLMUINT uiSubStringLen = f_strlen( pszSubString);
if( RC_BAD( rc = f_alloc( uiSubStringLen + 3, &pszSearch)))
{
goto Exit;
}
pszSearch[0] = '*';
f_memcpy( &pszSearch[ 1], pszSubString, uiSubStringLen);
pszSearch[ uiSubStringLen + 1] = '*';
pszSearch[ uiSubStringLen + 2] = '\0';
if( RC_BAD( rc = compareUTF8Strings(
pszString, f_strlen( pszString), FALSE, pszSearch,
uiSubStringLen + 2, TRUE, uiCompareRules, uiLanguage, &iResult)))
{
goto Exit;
}
*pbExists = (iResult)?FALSE:TRUE;
Exit:
if( pszSearch)
{
f_free( &pszSearch);
}
return( rc);
}