#include "dpiImpl.h"
int dpiUtils__allocateMemory(size_t numMembers, size_t memberSize,
int clearMemory, const char *action, void **ptr, dpiError *error)
{
if (clearMemory)
*ptr = calloc(numMembers, memberSize);
else *ptr = malloc(numMembers * memberSize);
if (!*ptr)
return dpiError__set(error, action, DPI_ERR_NO_MEMORY);
if (dpiDebugLevel & DPI_DEBUG_LEVEL_MEM)
dpiDebug__print("allocated %u bytes at %p (%s)\n",
numMembers * memberSize, *ptr, action);
return DPI_SUCCESS;
}
int dpiUtils__checkClientVersion(dpiVersionInfo *versionInfo,
int minVersionNum, int minReleaseNum, dpiError *error)
{
if (versionInfo->versionNum < minVersionNum ||
(versionInfo->versionNum == minVersionNum &&
versionInfo->releaseNum < minReleaseNum))
return dpiError__set(error, "check Oracle Client version",
DPI_ERR_ORACLE_CLIENT_TOO_OLD, versionInfo->versionNum,
versionInfo->releaseNum, minVersionNum, minReleaseNum);
return DPI_SUCCESS;
}
int dpiUtils__checkDatabaseVersion(dpiConn *conn, int minVersionNum,
int minReleaseNum, dpiError *error)
{
if (dpiConn__getServerVersion(conn, error) < 0)
return DPI_FAILURE;
if (conn->versionInfo.versionNum < minVersionNum ||
(conn->versionInfo.versionNum == minVersionNum &&
conn->versionInfo.releaseNum < minReleaseNum))
return dpiError__set(error, "check Oracle Database version",
DPI_ERR_ORACLE_DB_TOO_OLD, conn->versionInfo.versionNum,
conn->versionInfo.releaseNum, minVersionNum, minReleaseNum);
return DPI_SUCCESS;
}
void dpiUtils__clearMemory(void *ptr, size_t length)
{
volatile unsigned char *temp = (unsigned char *) ptr;
while (length--)
*temp++ = '\0';
}
void dpiUtils__freeMemory(void *ptr)
{
if (dpiDebugLevel & DPI_DEBUG_LEVEL_MEM)
dpiDebug__print("freed ptr at %p\n", ptr);
free(ptr);
}
int dpiUtils__getAttrStringWithDup(const char *action, const void *ociHandle,
uint32_t ociHandleType, uint32_t ociAttribute, const char **value,
uint32_t *valueLength, dpiError *error)
{
char *source, *temp;
if (dpiOci__attrGet(ociHandle, ociHandleType, (void*) &source,
valueLength, ociAttribute, action, error) < 0)
return DPI_FAILURE;
if (dpiUtils__allocateMemory(1, *valueLength, 0, action, (void**) &temp,
error) < 0)
return DPI_FAILURE;
*value = (const char*) memcpy(temp, source, *valueLength);
return DPI_SUCCESS;
}
int dpiUtils__parseNumberString(const char *value, uint32_t valueLength,
uint16_t charsetId, int *isNegative, int16_t *decimalPointIndex,
uint8_t *numDigits, uint8_t *digits, dpiError *error)
{
char convertedValue[DPI_NUMBER_AS_TEXT_CHARS], exponentDigits[4];
uint8_t numExponentDigits, digit;
uint32_t convertedValueLength;
uint16_t *utf16chars, i;
int exponentIsNegative;
const char *endValue;
int16_t exponent;
if (valueLength == 0)
return dpiError__set(error, "zero length", DPI_ERR_INVALID_NUMBER);
if ((charsetId == DPI_CHARSET_ID_UTF16 &&
valueLength > DPI_NUMBER_AS_TEXT_CHARS * 2) ||
(charsetId != DPI_CHARSET_ID_UTF16 &&
valueLength > DPI_NUMBER_AS_TEXT_CHARS))
return dpiError__set(error, "check length",
DPI_ERR_NUMBER_STRING_TOO_LONG);
if (charsetId == DPI_CHARSET_ID_UTF16) {
utf16chars = (uint16_t*) value;
convertedValue[0] = '\0';
convertedValueLength = valueLength / 2;
for (i = 0; i < convertedValueLength; i++) {
if (*utf16chars > 127)
return dpiError__set(error, "convert from UTF-16",
DPI_ERR_INVALID_NUMBER);
convertedValue[i] = (char) *utf16chars++;
}
value = convertedValue;
valueLength = convertedValueLength;
}
endValue = value + valueLength;
*isNegative = (*value == '-');
if (*isNegative)
value++;
*numDigits = 0;
while (value < endValue) {
if (*value == '.' || *value == 'e' || *value == 'E')
break;
if (*value < '0' || *value > '9')
return dpiError__set(error, "check digits before decimal point",
DPI_ERR_INVALID_NUMBER);
digit = (uint8_t) (*value++ - '0');
if (digit == 0 && *numDigits == 0)
continue;
*digits++ = digit;
(*numDigits)++;
}
*decimalPointIndex = *numDigits;
if (value < endValue && *value == '.') {
value++;
while (value < endValue) {
if (*value == 'e' || *value == 'E')
break;
if (*value < '0' || *value > '9')
return dpiError__set(error, "check digits after decimal point",
DPI_ERR_INVALID_NUMBER);
digit = (uint8_t) (*value++ - '0');
if (digit == 0 && *numDigits == 0) {
(*decimalPointIndex)--;
continue;
}
*digits++ = digit;
(*numDigits)++;
}
}
if (value < endValue && (*value == 'e' || *value == 'E')) {
value++;
exponentIsNegative = 0;
numExponentDigits = 0;
if (value < endValue && (*value == '+' || *value == '-')) {
exponentIsNegative = (*value == '-');
value++;
}
while (value < endValue) {
if (*value < '0' || *value > '9')
return dpiError__set(error, "check digits in exponent",
DPI_ERR_INVALID_NUMBER);
if (numExponentDigits == 3)
return dpiError__set(error, "check exponent digits > 3",
DPI_ERR_NOT_SUPPORTED);
exponentDigits[numExponentDigits] = *value++;
numExponentDigits++;
}
if (numExponentDigits == 0)
return dpiError__set(error, "no digits in exponent",
DPI_ERR_INVALID_NUMBER);
exponentDigits[numExponentDigits] = '\0';
exponent = (int16_t) strtol(exponentDigits, NULL, 10);
if (exponentIsNegative)
exponent = -exponent;
*decimalPointIndex += exponent;
}
if (value < endValue)
return dpiError__set(error, "check string used",
DPI_ERR_INVALID_NUMBER);
digits--;
while (*numDigits > 0 && *digits-- == 0)
(*numDigits)--;
if (*numDigits > DPI_NUMBER_MAX_DIGITS || *decimalPointIndex > 126 ||
*decimalPointIndex < -129) {
return dpiError__set(error, "check value can be represented",
DPI_ERR_NUMBER_NO_REPR);
}
return DPI_SUCCESS;
}
int dpiUtils__parseOracleNumber(void *oracleValue, int *isNegative,
int16_t *decimalPointIndex, uint8_t *numDigits, uint8_t *digits,
dpiError *error)
{
uint8_t *source, length, i, byte, digit;
int8_t ociExponent;
source = (uint8_t*) oracleValue;
length = *source++ - 1;
if (length > 20)
return dpiError__set(error, "check mantissa length",
DPI_ERR_INVALID_OCI_NUMBER);
ociExponent = (int8_t) *source++;
*isNegative = (ociExponent & 0x80) ? 0 : 1;
if (*isNegative)
ociExponent = ~ociExponent;
ociExponent -= 193;
*decimalPointIndex = ociExponent * 2 + 2;
if (length == 0) {
if (*isNegative) {
*digits = 1;
*decimalPointIndex = 127;
}
else {
*decimalPointIndex = 1;
*digits = 0;
}
*numDigits = 1;
return DPI_SUCCESS;
}
if (*isNegative && source[length - 1] == 102)
length--;
*numDigits = length * 2;
for (i = 0; i < length; i++) {
byte = *source++;
if (*isNegative)
byte = 101 - byte;
else byte--;
digit = (uint8_t) (byte / 10);
if (digit == 0 && i == 0) {
(*numDigits)--;
(*decimalPointIndex)--;
} else if (digit == 10) {
(*numDigits)++;
(*decimalPointIndex)++;
*digits++ = 1;
*digits++ = 0;
} else *digits++ = digit;
digit = byte % 10;
if (digit == 0 && i == length - 1)
(*numDigits)--;
else *digits++ = digit;
}
return DPI_SUCCESS;
}
int dpiUtils__setAttributesFromCommonCreateParams(void *handle,
uint32_t handleType, const dpiCommonCreateParams *params,
dpiError *error)
{
uint32_t driverNameLength;
const char *driverName;
if (params->driverName && params->driverNameLength > 0) {
driverName = params->driverName;
driverNameLength = params->driverNameLength;
} else {
driverName = DPI_DEFAULT_DRIVER_NAME;
driverNameLength = (uint32_t) strlen(driverName);
}
if (driverName && driverNameLength > 0 && dpiOci__attrSet(handle,
handleType, (void*) driverName, driverNameLength,
DPI_OCI_ATTR_DRIVER_NAME, "set driver name", error) < 0)
return DPI_FAILURE;
if (params->edition && params->editionLength > 0 &&
dpiOci__attrSet(handle, handleType,
(void*) params->edition, params->editionLength,
DPI_OCI_ATTR_EDITION, "set edition", error) < 0)
return DPI_FAILURE;
return DPI_SUCCESS;
}