windows-nt/Source/XPSP1/NT/admin/wmi/wbem/adapters/odbc/bcd.cpp

1147 lines
35 KiB
C++
Raw Normal View History

2020-09-26 03:20:57 -05:00
/***************************************************************************/
/* BCD.C */
/* Copyright (C) 1996 SYWARE Inc., All rights reserved */
/***************************************************************************/
// Commenting #define out - causing compiler error - not sure if needed, compiles
// okay without it.
//#define WINVER 0x0400
#include "precomp.h"
#include "wbemidl.h"
#include <comdef.h>
//smart pointer
_COM_SMARTPTR_TYPEDEF(IWbemServices, IID_IWbemServices);
_COM_SMARTPTR_TYPEDEF(IEnumWbemClassObject, IID_IEnumWbemClassObject);
//_COM_SMARTPTR_TYPEDEF(IWbemContext, IID_IWbemContext );
_COM_SMARTPTR_TYPEDEF(IWbemLocator, IID_IWbemLocator);
#include "drdbdr.h"
/***************************************************************************/
void INTFUNC BCDMultiplyByTen(LPUSTR lpszValue)
/* Multiply a value by ten */
{
SWORD decimal;
/* Look for the decimal point */
for (decimal = 0; decimal < s_lstrlen(lpszValue); decimal++) {
if (lpszValue[decimal] == '.') {
/* Found it. Move the next digit to the left */
lpszValue[decimal] = lpszValue[decimal+1];
/* Was the decimal point at the end of the value? */
if (lpszValue[decimal] != '\0') {
/* No. Set the next character to the decimal point */
lpszValue[decimal+1] = '.';
/* If no digits to the right of decimal point, remove it */
if (lpszValue[decimal+2] == '\0')
lpszValue[decimal+1] = '\0';
}
else {
/* Yes. Add in another zero */
lpszValue[decimal] = '0';
}
/* If we just moved a zero to the left of the decimal point */
/* for a number with only a fractional part, remove the */
/* leading zero */
if (*lpszValue == '0')
s_lstrcpy(lpszValue, lpszValue + 1);
return;
}
}
/* Didn't find a decimal point. Just add a zero to the end */
if (s_lstrlen(lpszValue) != 0)
s_lstrcat(lpszValue, "0");
return;
}
/***************************************************************************/
void INTFUNC BCDDivideByTen(LPUSTR lpszValue)
/* Divide a value by ten */
{
SWORD decimal;
/* Look for the decimal point */
for (decimal = 0; decimal < s_lstrlen(lpszValue); decimal++) {
if (lpszValue[decimal] == '.') {
/* Found it. Is this the first character? */
if (decimal != 0) {
/* No. Move the previous digit into this spot */
lpszValue[decimal] = lpszValue[decimal-1];
/* Put in the new decimal point */
lpszValue[decimal-1] = '.';
}
else {
/* Yes. move the number to the right */
_fmemmove(lpszValue+1, lpszValue, s_lstrlen(lpszValue)+1);
/* Add in another zero */
lpszValue[1] = '0';
}
return;
}
}
/* Didn't find a decimal point. Move right most digit over and */
/* add one in */
if (decimal > 0) {
lpszValue[decimal+1] = '\0';
lpszValue[decimal] = lpszValue[decimal-1];
lpszValue[decimal-1] = '.';
}
return;
}
/***************************************************************************/
SWORD INTFUNC BCDCompareValues(LPUSTR lpszLeft,
LPUSTR lpszRight)
/* Compares the two BCD values. The values are assumed to be positive */
/* If 'lpszLeft' is greater than 'lpszRight', a positive value is retuned. */
/* If 'lpszLeft' is less than 'lpszRight', a negative value is retuned. */
/* If 'lpszLeft' is equal to 'lpszRight', 0 is retuned. */
{
SWORD idxDecimalLeft;
SWORD idxDecimalRight;
UCHAR cLeft;
UCHAR cRight;
LPUSTR ptrLeft;
LPUSTR ptrRight;
int fComp;
/* Find decimal point (if any) */
for (idxDecimalLeft = 0;
idxDecimalLeft < s_lstrlen(lpszLeft);
idxDecimalLeft++) {
if (lpszLeft[idxDecimalLeft] == '.')
break;
}
for (idxDecimalRight = 0;
idxDecimalRight < s_lstrlen(lpszRight);
idxDecimalRight++) {
if (lpszRight[idxDecimalRight] == '.')
break;
}
/* If unequal number of integer digits, return answer */
if (idxDecimalLeft > idxDecimalRight)
return 1;
else if (idxDecimalLeft < idxDecimalRight)
return -1;
/* Compare integer part of the values and if they are not equal, */
/* return answer */
cLeft = lpszLeft[idxDecimalLeft];
cRight = lpszRight[idxDecimalRight];
lpszLeft[idxDecimalLeft] = '\0';
if (lpszRight[idxDecimalRight] != '\0')
lpszRight[idxDecimalRight] = '\0';
fComp = s_lstrcmp(lpszLeft, lpszRight);
lpszLeft[idxDecimalLeft] = cLeft;
if (lpszRight[idxDecimalRight] != cRight)
lpszRight[idxDecimalRight] = cRight;
if (fComp > 0)
return 1;
else if (fComp < 0)
return -1;
/* The integer parts are equal. Compare the fractional parts */
ptrLeft = lpszLeft + idxDecimalLeft;
if (*ptrLeft == '.')
ptrLeft++;
ptrRight = lpszRight + idxDecimalRight;
if (*ptrRight == '.')
ptrRight++;
while (TRUE) {
if (*ptrLeft == '\0') {
while (*ptrRight == '0')
ptrRight++;
if (*ptrRight == '\0')
break;
return -1;
}
if (*ptrRight == '\0') {
while (*ptrLeft == '0')
ptrLeft++;
if (*ptrLeft == '\0')
break;
return 1;
}
if (*ptrLeft > *ptrRight)
return 1;
else if (*ptrLeft < *ptrRight)
return -1;
ptrLeft++;
ptrRight++;
}
return 0;
}
/***************************************************************************/
void INTFUNC BCDAdd(LPUSTR lpszResult,
LPUSTR lpszLeft,
LPUSTR lpszRight)
{
LPUSTR lpszCurrent;
LPUSTR lpszCurrentLeft;
LPUSTR lpszCurrentRight;
SWORD idxDecimalLeft;
SWORD idxDecimalRight;
UCHAR digit;
LPUSTR lpszCarryDigit;
/* Point at values */
lpszCurrent = lpszResult;
lpszCurrentLeft = lpszLeft;
lpszCurrentRight = lpszRight;
/* Put leading zero in */
*lpszCurrent = '0';
lpszCurrent++;
/* Find decimal point (if any) */
for (idxDecimalLeft = 0;
idxDecimalLeft < s_lstrlen(lpszLeft);
idxDecimalLeft++) {
if (lpszLeft[idxDecimalLeft] == '.')
break;
}
for (idxDecimalRight = 0;
idxDecimalRight < s_lstrlen(lpszRight);
idxDecimalRight++) {
if (lpszRight[idxDecimalRight] == '.')
break;
}
/* Put in excess characters */
while (idxDecimalLeft > idxDecimalRight) {
*lpszCurrent = *lpszCurrentLeft;
lpszCurrent++;
lpszCurrentLeft++;
idxDecimalLeft--;
}
while (idxDecimalRight > idxDecimalLeft) {
*lpszCurrent = *lpszCurrentRight;
lpszCurrent++;
lpszCurrentRight++;
idxDecimalRight--;
}
/* Add integer part */
while (idxDecimalLeft > 0) {
/* Get left digit */
digit = (*lpszCurrentLeft) & 0x0F;
lpszCurrentLeft++;
idxDecimalLeft--;
/* Add right digit to it */
digit += ((*lpszCurrentRight) & 0x0F);
lpszCurrentRight++;
idxDecimalRight--;
/* Is there a carry? */
if (digit >= 10) {
/* Yes. Propagate it to the higher digits */
lpszCarryDigit = lpszCurrent - 1;
while (TRUE) {
if (*lpszCarryDigit != '9') {
*lpszCarryDigit = *lpszCarryDigit + 1;
break;
}
*lpszCarryDigit = '0';
lpszCarryDigit--;
}
/* Adjust digit */
digit -= (10);
}
/* Save digit */
*lpszCurrent = '0' + digit;
lpszCurrent++;
}
/* Is there a fractional part? */
if ((*lpszCurrentLeft != '\0') || (*lpszCurrentRight != '\0')) {
/* Yes. Put in a decimal point */
*lpszCurrent = '.';
lpszCurrent++;
/* Skip over the decimal points */
if (*lpszCurrentRight == '.')
lpszCurrentRight++;
if (*lpszCurrentLeft == '.')
lpszCurrentLeft++;
/* Add the values */
while ((*lpszCurrentLeft != '\0') || (*lpszCurrentRight != '\0')) {
/* Get left digit */
if (*lpszCurrentLeft != '\0') {
digit = (*lpszCurrentLeft) & 0x0F;
lpszCurrentLeft++;
}
else
digit = 0;
/* Add right digit to it */
if (*lpszCurrentRight != '\0') {
digit += ((*lpszCurrentRight) & 0x0F);
lpszCurrentRight++;
}
/* Is there a carry? */
if (digit >= 10) {
/* Yes. Propagate it to the higher digits */
lpszCarryDigit = lpszCurrent - 1;
while (TRUE) {
if (*lpszCarryDigit == '.')
lpszCarryDigit--;
if (*lpszCarryDigit != '9') {
*lpszCarryDigit = *lpszCarryDigit + 1;
break;
}
*lpszCarryDigit = '0';
lpszCarryDigit--;
}
/* Adjust digit */
digit -= (10);
}
/* Save digit */
*lpszCurrent = '0' + digit;
lpszCurrent++;
}
}
/* Put in terminating null */
*lpszCurrent = '\0';
/* Did anything carry into the first digit? */
if (*lpszResult == '0') {
/* No. Shift value to the left */
s_lstrcpy(lpszResult, lpszResult+1);
}
}
/***************************************************************************/
void INTFUNC BCDSubtract(LPUSTR lpszResult,
LPUSTR lpszLeft,
LPUSTR lpszRight)
{
LPUSTR lpszCurrent;
LPUSTR lpszCurrentLeft;
LPUSTR lpszCurrentRight;
SWORD idxDecimalLeft;
SWORD idxDecimalRight;
UCHAR digit;
LPUSTR lpszBorrowDigit;
/* If the result is negative, subtract the other way */
if (BCDCompareValues(lpszLeft, lpszRight) < 0) {
*lpszResult = '-';
BCDSubtract(lpszResult+1, lpszRight, lpszLeft);
return;
}
/* Point at values */
lpszCurrent = lpszResult;
lpszCurrentLeft = lpszLeft;
lpszCurrentRight = lpszRight;
/* Find decimal point (if any) */
for (idxDecimalLeft = 0;
idxDecimalLeft < s_lstrlen(lpszLeft);
idxDecimalLeft++) {
if (lpszLeft[idxDecimalLeft] == '.')
break;
}
for (idxDecimalRight = 0;
idxDecimalRight < s_lstrlen(lpszRight);
idxDecimalRight++) {
if (lpszRight[idxDecimalRight] == '.')
break;
}
/* Put in excess characters */
while (idxDecimalLeft > idxDecimalRight) {
*lpszCurrent = *lpszCurrentLeft;
lpszCurrent++;
lpszCurrentLeft++;
idxDecimalLeft--;
}
/* Subtract integer part */
while (idxDecimalLeft > 0) {
/* Get left digit */
digit = (*lpszCurrentLeft) & 0x0F;
lpszCurrentLeft++;
idxDecimalLeft--;
/* Add ten to it (to keep it positive) */
digit += (10);
/* Subtract right digit from it */
digit -= ((*lpszCurrentRight) & 0x0F);
lpszCurrentRight++;
idxDecimalRight--;
/* Is there a borrow? */
if (digit < 10) {
/* Yes. Propagate it to the higher digits */
lpszBorrowDigit = lpszCurrent - 1;
while (TRUE) {
if (*lpszBorrowDigit != '0') {
*lpszBorrowDigit = *lpszBorrowDigit - 1;
break;
}
*lpszBorrowDigit = '9';
lpszBorrowDigit--;
}
}
else {
/* No. Adjust digit */
digit -= (10);
}
/* Save digit */
*lpszCurrent = '0' + digit;
lpszCurrent++;
}
/* Is there a fractional part? */
if ((*lpszCurrentLeft != '\0') || (*lpszCurrentRight != '\0')) {
/* Yes. Put in a decimal point */
*lpszCurrent = '.';
lpszCurrent++;
/* Skip over the decimal points */
if (*lpszCurrentRight == '.')
lpszCurrentRight++;
if (*lpszCurrentLeft == '.')
lpszCurrentLeft++;
/* Subtract the values */
while ((*lpszCurrentLeft != '\0') || (*lpszCurrentRight != '\0')) {
/* Get left digit */
if (*lpszCurrentLeft != '\0') {
digit = (*lpszCurrentLeft) & 0x0F;
lpszCurrentLeft++;
}
else
digit = 0;
/* Add ten to it (to keep it positive) */
digit += (10);
/* Subtract right digit from it */
if (*lpszCurrentRight != '\0') {
digit -= ((*lpszCurrentRight) & 0x0F);
lpszCurrentRight++;
}
/* Is there a borrow? */
if (digit < 10) {
/* Yes. Propagate it to the higher digits */
lpszBorrowDigit = lpszCurrent - 1;
while (TRUE) {
if (*lpszBorrowDigit == '.')
lpszBorrowDigit--;
if (*lpszBorrowDigit != '0') {
*lpszBorrowDigit = *lpszBorrowDigit - 1;
break;
}
*lpszBorrowDigit = '9';
lpszBorrowDigit--;
}
}
else {
/* No. Adjust digit */
digit -= (10);
}
/* Save digit */
*lpszCurrent = '0' + digit;
lpszCurrent++;
}
}
/* Put in terminating null */
*lpszCurrent = '\0';
/* Remove leading zeros */
while (*lpszResult == '0')
s_lstrcpy(lpszResult, lpszResult+1);
}
/***************************************************************************/
void INTFUNC BCDTimes(LPUSTR lpszResult,
LPUSTR lpszLeft,
LPUSTR lpszRight,
LPUSTR lpWorkBuffer)
{
SWORD idxDecimalLeft;
SWORD idxDecimalRight;
SWORD cDecimalDigits;
LPUSTR lpszCurrent;
UCHAR digit;
UCHAR idx;
/* Find decimal point (if any) */
for (idxDecimalLeft = 0;
idxDecimalLeft < s_lstrlen(lpszLeft);
idxDecimalLeft++) {
if (lpszLeft[idxDecimalLeft] == '.')
break;
}
for (idxDecimalRight = 0;
idxDecimalRight < s_lstrlen(lpszRight);
idxDecimalRight++) {
if (lpszRight[idxDecimalRight] == '.')
break;
}
/* Remove decimal points from the values and figure out how many */
/* decimal digits in the result */
if (*(lpszLeft + idxDecimalLeft) == '.') {
_fmemmove(lpszLeft + idxDecimalLeft, lpszLeft + idxDecimalLeft + 1,
s_lstrlen(lpszLeft + idxDecimalLeft));
cDecimalDigits = s_lstrlen(lpszLeft) - idxDecimalLeft;
}
else {
cDecimalDigits = 0;
idxDecimalLeft = -1;
}
if (*(lpszRight + idxDecimalRight) == '.') {
_fmemmove(lpszRight + idxDecimalRight, lpszRight + idxDecimalRight + 1,
s_lstrlen(lpszRight + idxDecimalRight));
cDecimalDigits += (s_lstrlen(lpszRight) - idxDecimalRight);
}
else
idxDecimalRight = -1;
/* Put a zero in the workbuffer */
s_lstrcpy(lpWorkBuffer, lpszRight);
for (lpszCurrent = lpWorkBuffer; *lpszCurrent; lpszCurrent++)
*lpszCurrent = '0';
/* For each left digit... */
lpszCurrent = lpszLeft;
while (*lpszCurrent != '\0') {
/* Add the right value into the result that many times */
digit = *lpszCurrent & 0x0F;
for (idx = 0; idx < digit; idx++) {
BCDAdd(lpszResult, lpszRight, lpWorkBuffer);
s_lstrcpy(lpWorkBuffer, lpszResult);
}
/* Look at next digit */
lpszCurrent++;
if (*lpszCurrent == '\0')
break;
/* Multiply the result by ten */
s_lstrcat(lpWorkBuffer, "0");
}
s_lstrcpy(lpszResult, lpWorkBuffer);
/* Put the decimal point back into the values */
if (idxDecimalLeft != -1) {
_fmemmove(lpszLeft + idxDecimalLeft + 1, lpszLeft + idxDecimalLeft,
s_lstrlen(lpszLeft + idxDecimalLeft) + 1);
lpszLeft[idxDecimalLeft] = '.';
}
if (idxDecimalRight != -1) {
_fmemmove(lpszRight + idxDecimalRight + 1, lpszRight + idxDecimalRight,
s_lstrlen(lpszRight + idxDecimalRight) + 1);
lpszRight[idxDecimalRight] = '.';
}
if (cDecimalDigits != 0) {
while (s_lstrlen(lpszResult) < cDecimalDigits) {
_fmemmove(lpszResult + 1, lpszResult, s_lstrlen(lpszResult)+1);
lpszResult[0] = '0';
}
_fmemmove(lpszResult + s_lstrlen(lpszResult) - cDecimalDigits + 1,
lpszResult + s_lstrlen(lpszResult) - cDecimalDigits,
s_lstrlen(lpszResult + s_lstrlen(lpszResult) - cDecimalDigits)+1);
lpszResult[s_lstrlen(lpszResult) - cDecimalDigits - 1] = '.';
}
return;
}
/***************************************************************************/
SWORD INTFUNC BCDDivide(LPUSTR lpszResult,
SWORD scale,
LPUSTR lpszLeft,
LPUSTR lpszRight,
LPUSTR lpWorkBuffer1,
LPUSTR lpWorkBuffer2,
LPUSTR lpWorkBuffer3)
{
SWORD decimalPosition;
LPUSTR lpszCurrent;
SWORD i;
/* If right side is zero, return an error */
for (lpszCurrent = lpszRight; *lpszCurrent; lpszCurrent++){
if ((*lpszCurrent != '0') && (*lpszCurrent != '.'))
break;
}
if (*lpszCurrent == '\0')
return ERR_ZERODIVIDE;
/* Copy the dividend */
if (BCDCompareValues(lpszLeft, (LPUSTR)"") != 0)
s_lstrcpy(lpWorkBuffer1, lpszLeft);
else
s_lstrcpy(lpWorkBuffer1, "");
/* 'decimalPosition' specifies how places the decimal point has to be */
/* moved. Positive values mean move to the right, negative values */
/* mean move to the left */
decimalPosition = 0;
/* While the dividend is greater than the divisor, divide it by ten. */
while (BCDCompareValues(lpWorkBuffer1, lpszRight) > 0) {
BCDDivideByTen(lpWorkBuffer1);
decimalPosition++;
}
/* While the dividend is less than the divisor, multiply it by ten. */
if (s_lstrlen(lpWorkBuffer1) > 0) {
while (BCDCompareValues(lpWorkBuffer1, lpszRight) < 0) {
BCDMultiplyByTen(lpWorkBuffer1);
decimalPosition--;
}
}
/* Point at place to put result */
lpszCurrent = lpszResult;
/* If the scale is greater than zero, put in the decimal point */
if (scale > 0) {
*lpszCurrent = '.';
lpszCurrent++;
}
decimalPosition++;
/* For as many digits as are needed... */
s_lstrcpy(lpWorkBuffer2, lpszRight);
for (i = 0; i < scale + decimalPosition; i++) {
/* Intialize the digit to zero */
*lpszCurrent = '0';
/* Count how many times divisor can be subtracted from dividend */
while (BCDCompareValues(lpWorkBuffer1, lpWorkBuffer2) >= 0) {
s_lstrcpy(lpWorkBuffer3, lpWorkBuffer1);
BCDSubtract(lpWorkBuffer1, lpWorkBuffer3, lpWorkBuffer2);
(*lpszCurrent)++;
}
/* Calculate the next digit of the result */
lpszCurrent++;
BCDDivideByTen(lpWorkBuffer2);
}
*lpszCurrent = '\0';
/* If there is a positive scale, move the decimal point as need be */
if (scale > 0) {
while (decimalPosition > 0) {
BCDMultiplyByTen(lpszResult);
decimalPosition--;
}
while (decimalPosition < 0) {
BCDDivideByTen(lpszResult);
decimalPosition++;
}
}
/* Remove leading zeros */
while (*lpszResult == '0')
s_lstrcpy(lpszResult, lpszResult+1);
return ERR_SUCCESS;
}
/***************************************************************************/
void INTFUNC BCDFixNegZero(LPUSTR szValue,
SDWORD cbValueMax)
/* Change "-0.000" to "0.000" if need be */
{
LPUSTR toPtr;
SWORD idx;
BOOL fZero;
/* Is this a negative number? */
if ((cbValueMax > 0) && (*szValue == '-')) {
/* Yes. Figure out if it is zero */
fZero = TRUE;
toPtr = szValue + 1;
for (idx = 0; idx < cbValueMax-1; idx++) {
if (*toPtr == '\0')
break;
if ((*toPtr != '.') && (*toPtr != '0')) {
fZero = FALSE;
break;
}
toPtr++;
}
/* If it is zero, remove leading minus sign */
if (fZero) {
toPtr = szValue;
for (idx = 1; idx < cbValueMax-1; idx++) {
*toPtr = *(toPtr + 1);
if (*toPtr == '\0')
break;
toPtr++;
}
*toPtr = '\0';
}
}
}
/***************************************************************************/
/***************************************************************************/
SWORD INTFUNC BCDNormalize(LPUSTR szValueFrom,
SDWORD cbValueFrom,
LPUSTR szValueTo,
SDWORD cbValueToMax,
SDWORD precision,
SWORD scale)
{
LPUSTR toPtr;
SDWORD toSize;
SDWORD idxDecimalPoint;
SWORD idx;
BOOL fNegative;
BOOL fTruncated;
SDWORD right;
SDWORD left;
/* Point to destination */
toPtr = szValueTo;
toSize = cbValueToMax;
/* Trim off leading spaces */
while ((cbValueFrom > 0) && (*szValueFrom == ' ')) {
szValueFrom++;
cbValueFrom--;
}
/* See if value is positive or negative */
if (*szValueFrom != '-')
fNegative = FALSE;
else {
fNegative = TRUE;
szValueFrom++;
cbValueFrom--;
}
/* Trim off leading zeros */
while ((cbValueFrom > 0) && (*szValueFrom == '0')) {
szValueFrom++;
cbValueFrom--;
}
/* Trim off trailing spaces */
while ((cbValueFrom > 0) && (szValueFrom[cbValueFrom - 1] == ' '))
cbValueFrom--;
/* Is there a decimal point? */
for (idx = 0; idx < cbValueFrom; idx++) {
if (szValueFrom[idx] == '.') {
/* Yes. Trim off trailing zeros */
while ((cbValueFrom > 0) && (szValueFrom[cbValueFrom - 1] == '0'))
cbValueFrom--;
break;
}
}
/* Find location of decimal point (if any) */
idxDecimalPoint = -1;
for (idx = 0; idx < cbValueFrom; idx++) {
if (szValueFrom[idx] == '.') {
idxDecimalPoint = idx;
break;
}
}
/* If scale is zero, remove decimal point and digits */
fTruncated = FALSE;
if ((idxDecimalPoint != -1) && (scale == 0)) {
if (idxDecimalPoint < (cbValueFrom - 1))
fTruncated = TRUE;
cbValueFrom = idxDecimalPoint;
idxDecimalPoint = -1;
}
/* Figure out how many digits to the right of the decimal point */
if (idxDecimalPoint == -1)
right = 0;
else
right = cbValueFrom - idxDecimalPoint - 1;
/* If too many digits to the right of the decimal point, remove them */
while (right > scale) {
cbValueFrom--;
right--;
fTruncated = TRUE;
}
/* Figure out how many digits to the left of the decimal point */
if (idxDecimalPoint == -1)
left = cbValueFrom;
else
left = cbValueFrom - right - 1;
/* If too many digits to the left of the decimal point, error */
if (left > (precision - scale))
return ERR_OUTOFRANGE;
/* Copy the value to the output buffer. If negative put in the sign */
if (fNegative) {
if (toSize > 0) {
*toPtr = '-';
toPtr++;
toSize--;
}
else
return ERR_OUTOFRANGE;
}
/* Put the digits to the left of the decimal in */
while (left > 0) {
if (toSize > 0) {
*toPtr = *szValueFrom;
szValueFrom++;
toPtr++;
toSize--;
}
else
return ERR_OUTOFRANGE;
left--;
}
/* Decimal part needed? */
if (scale > 0) {
/* Put in the decimal point */
if (toSize > 0) {
*toPtr = '.';
toPtr++;
toSize--;
}
else
fTruncated = TRUE;
/* Put in the decimal digits */
if (idxDecimalPoint != -1)
szValueFrom++;
while (scale > 0) {
if (toSize > 0) {
if (right > 0) {
*toPtr = *szValueFrom;
szValueFrom++;
right--;
}
else {
*toPtr = '0';
}
toPtr++;
toSize--;
}
else
fTruncated = TRUE;
scale--;
}
}
/* Put in null terminator */
if (toSize > 0) {
*toPtr = '\0';
toPtr++;
toSize--;
}
else
fTruncated = TRUE;
BCDFixNegZero(szValueTo, cbValueToMax);
if (fTruncated)
return ERR_DATATRUNCATED;
return ERR_SUCCESS;
}
/***************************************************************************/
RETCODE INTFUNC BCDCompare(LPSQLNODE lpSqlNode, LPSQLNODE lpSqlNodeLeft,
UWORD Operator, LPSQLNODE lpSqlNodeRight)
/* Compares two BCD values as follows: */
/* lpSqlNode->value.Double = lpSqlNodeLeft Operator lpSqlNodeRight */
{
SWORD fComp;
/* Check parameters */
if ((lpSqlNode->sqlDataType != TYPE_INTEGER) ||
(lpSqlNodeLeft->sqlDataType != TYPE_NUMERIC) ||
((Operator != OP_NEG)&&(lpSqlNodeRight->sqlDataType != TYPE_NUMERIC)))
return ERR_INTERNAL;
/* Compare the values */
if ((lpSqlNodeLeft->value.String[0] != '-') &&
(lpSqlNodeRight->value.String[0] != '-')) {
fComp = BCDCompareValues(lpSqlNodeLeft->value.String,
lpSqlNodeRight->value.String);
}
else if ((lpSqlNodeLeft->value.String[0] != '-') &&
(lpSqlNodeRight->value.String[0] == '-'))
fComp = 1;
else if ((lpSqlNodeLeft->value.String[0] == '-') &&
(lpSqlNodeRight->value.String[0] != '-'))
fComp = -1;
else {
fComp = BCDCompareValues(lpSqlNodeRight->value.String+1,
lpSqlNodeLeft->value.String+1);
}
/* Figure out the answer */
switch (Operator) {
case OP_EQ:
if (fComp == 0)
lpSqlNode->value.Double = TRUE;
else
lpSqlNode->value.Double = FALSE;
break;
case OP_NE:
if (fComp != 0)
lpSqlNode->value.Double = TRUE;
else
lpSqlNode->value.Double = FALSE;
break;
case OP_LE:
if (fComp <= 0)
lpSqlNode->value.Double = TRUE;
else
lpSqlNode->value.Double = FALSE;
break;
case OP_LT:
if (fComp < 0)
lpSqlNode->value.Double = TRUE;
else
lpSqlNode->value.Double = FALSE;
break;
case OP_GE:
if (fComp >= 0)
lpSqlNode->value.Double = TRUE;
else
lpSqlNode->value.Double = FALSE;
break;
case OP_GT:
if (fComp > 0)
lpSqlNode->value.Double = TRUE;
else
lpSqlNode->value.Double = FALSE;
break;
case OP_LIKE:
case OP_NOTLIKE:
default:
return ERR_INTERNAL;
}
return ERR_SUCCESS;
}
/***************************************************************************/
RETCODE INTFUNC BCDAlgebra(LPSQLNODE lpSqlNode, LPSQLNODE lpSqlNodeLeft,
UWORD Operator, LPSQLNODE lpSqlNodeRight,
LPUSTR lpWorkBuffer1, LPUSTR lpWorkBuffer2,
LPUSTR lpWorkBuffer3)
/* Perfoms algebraic operation in two numerical values as follows: */
/* lpSqlNode lpSqlNodeLeft Operator lpSqlNodeRight */
{
RETCODE err;
/* Check parameters */
if ((Operator != OP_NEG) && (lpSqlNodeRight == NULL))
return ERR_INTERNAL;
if ((lpSqlNode->sqlDataType != TYPE_NUMERIC) ||
(lpSqlNodeLeft->sqlDataType != TYPE_NUMERIC) ||
((Operator != OP_NEG)&&(lpSqlNodeRight->sqlDataType != TYPE_NUMERIC)))
return ERR_INTERNAL;
/* Do the operation */
switch (Operator) {
case OP_NEG:
if (lpSqlNodeLeft->value.String[0] == '-')
s_lstrcpy(lpSqlNode->value.String, lpSqlNodeLeft->value.String+1);
else {
lpSqlNode->value.String[0] = '-';
s_lstrcpy(lpSqlNode->value.String+1, lpSqlNodeLeft->value.String);
}
break;
case OP_PLUS:
if ((lpSqlNodeLeft->value.String[0] != '-') &&
(lpSqlNodeRight->value.String[0] != '-')) {
BCDAdd(lpSqlNode->value.String,
lpSqlNodeLeft->value.String,
lpSqlNodeRight->value.String);
}
else if ((lpSqlNodeLeft->value.String[0] != '-') &&
(lpSqlNodeRight->value.String[0] == '-')) {
BCDSubtract(lpSqlNode->value.String,
lpSqlNodeLeft->value.String,
lpSqlNodeRight->value.String+1);
}
else if ((lpSqlNodeLeft->value.String[0] == '-') &&
(lpSqlNodeRight->value.String[0] != '-')) {
BCDSubtract(lpSqlNode->value.String,
lpSqlNodeRight->value.String,
lpSqlNodeLeft->value.String+1);
}
else {
lpSqlNode->value.String[0] = '-';
BCDAdd(lpSqlNode->value.String+1,
lpSqlNodeLeft->value.String+1,
lpSqlNodeRight->value.String+1);
}
break;
case OP_MINUS:
if ((lpSqlNodeLeft->value.String[0] != '-') &&
(lpSqlNodeRight->value.String[0] != '-')) {
BCDSubtract(lpSqlNode->value.String,
lpSqlNodeLeft->value.String,
lpSqlNodeRight->value.String);
}
else if ((lpSqlNodeLeft->value.String[0] != '-') &&
(lpSqlNodeRight->value.String[0] == '-')) {
BCDAdd(lpSqlNode->value.String,
lpSqlNodeLeft->value.String,
lpSqlNodeRight->value.String+1);
}
else if ((lpSqlNodeLeft->value.String[0] == '-') &&
(lpSqlNodeRight->value.String[0] != '-')) {
lpSqlNode->value.String[0] = '-';
BCDAdd(lpSqlNode->value.String+1,
lpSqlNodeLeft->value.String+1,
lpSqlNodeRight->value.String);
}
else {
BCDSubtract(lpSqlNode->value.String,
lpSqlNodeRight->value.String+1,
lpSqlNodeLeft->value.String+1);
}
break;
case OP_TIMES:
if ((lpSqlNodeLeft->value.String[0] != '-') &&
(lpSqlNodeRight->value.String[0] != '-')) {
BCDTimes(lpSqlNode->value.String,
lpSqlNodeLeft->value.String,
lpSqlNodeRight->value.String,
lpWorkBuffer1);
}
else if ((lpSqlNodeLeft->value.String[0] != '-') &&
(lpSqlNodeRight->value.String[0] == '-')) {
lpSqlNode->value.String[0] = '-';
BCDTimes(lpSqlNode->value.String+1,
lpSqlNodeLeft->value.String,
lpSqlNodeRight->value.String+1,
lpWorkBuffer1);
}
else if ((lpSqlNodeLeft->value.String[0] == '-') &&
(lpSqlNodeRight->value.String[0] != '-')) {
lpSqlNode->value.String[0] = '-';
BCDTimes(lpSqlNode->value.String+1,
lpSqlNodeLeft->value.String+1,
lpSqlNodeRight->value.String,
lpWorkBuffer1);
}
else {
BCDTimes(lpSqlNode->value.String,
lpSqlNodeLeft->value.String+1,
lpSqlNodeRight->value.String+1,
lpWorkBuffer1);
}
break;
case OP_DIVIDEDBY:
if ((lpSqlNodeLeft->value.String[0] != '-') &&
(lpSqlNodeRight->value.String[0] != '-')) {
err = BCDDivide(lpSqlNode->value.String,
lpSqlNode->sqlScale,
lpSqlNodeLeft->value.String,
lpSqlNodeRight->value.String,
lpWorkBuffer1, lpWorkBuffer2, lpWorkBuffer3);
}
else if ((lpSqlNodeLeft->value.String[0] != '-') &&
(lpSqlNodeRight->value.String[0] == '-')) {
lpSqlNode->value.String[0] = '-';
err = BCDDivide(lpSqlNode->value.String+1,
lpSqlNode->sqlScale,
lpSqlNodeLeft->value.String,
lpSqlNodeRight->value.String+1,
lpWorkBuffer1, lpWorkBuffer2, lpWorkBuffer3);
}
else if ((lpSqlNodeLeft->value.String[0] == '-') &&
(lpSqlNodeRight->value.String[0] != '-')) {
lpSqlNode->value.String[0] = '-';
err = BCDDivide(lpSqlNode->value.String+1,
lpSqlNode->sqlScale,
lpSqlNodeLeft->value.String+1,
lpSqlNodeRight->value.String,
lpWorkBuffer1, lpWorkBuffer2, lpWorkBuffer3);
}
else {
err = BCDDivide(lpSqlNode->value.String,
lpSqlNode->sqlScale,
lpSqlNodeLeft->value.String+1,
lpSqlNodeRight->value.String+1,
lpWorkBuffer1, lpWorkBuffer2, lpWorkBuffer3);
}
if (err != ERR_SUCCESS)
return err;
break;
default:
return ERR_INTERNAL;
}
BCDFixNegZero(lpSqlNode->value.String,s_lstrlen(lpSqlNode->value.String)+1);
return ERR_SUCCESS;
}
/***************************************************************************/