609 lines
22 KiB
C
609 lines
22 KiB
C
//-----------------------------------------------------------------------------
|
|
// NumberVar.c
|
|
// Defines the routines for handling numeric variables.
|
|
//-----------------------------------------------------------------------------
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Number types
|
|
//-----------------------------------------------------------------------------
|
|
typedef struct {
|
|
Variable_HEAD
|
|
OCINumber *data;
|
|
} udt_NumberVar;
|
|
|
|
|
|
#ifdef SQLT_BFLOAT
|
|
typedef struct {
|
|
Variable_HEAD
|
|
double *data;
|
|
} udt_NativeFloatVar;
|
|
#endif
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Declaration of number variable functions.
|
|
//-----------------------------------------------------------------------------
|
|
static int NumberVar_PreDefine(udt_NumberVar*, OCIParam*);
|
|
static int NumberVar_SetValue(udt_NumberVar*, unsigned, PyObject*);
|
|
static PyObject *NumberVar_GetValue(udt_NumberVar*, unsigned);
|
|
#ifdef SQLT_BFLOAT
|
|
static int NativeFloatVar_SetValue(udt_NativeFloatVar*, unsigned, PyObject*);
|
|
static PyObject *NativeFloatVar_GetValue(udt_NativeFloatVar*, unsigned);
|
|
#endif
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Python type declaration
|
|
//-----------------------------------------------------------------------------
|
|
static PyTypeObject g_NumberVarType = {
|
|
PyVarObject_HEAD_INIT(NULL, 0)
|
|
"cx_Oracle.NUMBER", // tp_name
|
|
sizeof(udt_NumberVar), // tp_basicsize
|
|
0, // tp_itemsize
|
|
0, // tp_dealloc
|
|
0, // tp_print
|
|
0, // tp_getattr
|
|
0, // tp_setattr
|
|
0, // tp_compare
|
|
0, // tp_repr
|
|
0, // tp_as_number
|
|
0, // tp_as_sequence
|
|
0, // tp_as_mapping
|
|
0, // tp_hash
|
|
0, // tp_call
|
|
0, // tp_str
|
|
0, // tp_getattro
|
|
0, // tp_setattro
|
|
0, // tp_as_buffer
|
|
Py_TPFLAGS_DEFAULT, // tp_flags
|
|
0 // tp_doc
|
|
};
|
|
|
|
|
|
#ifdef SQLT_BFLOAT
|
|
static PyTypeObject g_NativeFloatVarType = {
|
|
PyVarObject_HEAD_INIT(NULL, 0)
|
|
"cx_Oracle.NATIVE_FLOAT", // tp_name
|
|
sizeof(udt_NativeFloatVar), // tp_basicsize
|
|
0, // tp_itemsize
|
|
0, // tp_dealloc
|
|
0, // tp_print
|
|
0, // tp_getattr
|
|
0, // tp_setattr
|
|
0, // tp_compare
|
|
0, // tp_repr
|
|
0, // tp_as_number
|
|
0, // tp_as_sequence
|
|
0, // tp_as_mapping
|
|
0, // tp_hash
|
|
0, // tp_call
|
|
0, // tp_str
|
|
0, // tp_getattro
|
|
0, // tp_setattro
|
|
0, // tp_as_buffer
|
|
Py_TPFLAGS_DEFAULT, // tp_flags
|
|
0 // tp_doc
|
|
};
|
|
#endif
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// variable type declarations
|
|
//-----------------------------------------------------------------------------
|
|
static udt_VariableType vt_Float = {
|
|
(InitializeProc) NULL,
|
|
(FinalizeProc) NULL,
|
|
(PreDefineProc) NumberVar_PreDefine,
|
|
(PostDefineProc) NULL,
|
|
(PreFetchProc) NULL,
|
|
(IsNullProc) NULL,
|
|
(SetValueProc) NumberVar_SetValue,
|
|
(GetValueProc) NumberVar_GetValue,
|
|
(GetBufferSizeProc) NULL,
|
|
&g_NumberVarType, // Python type
|
|
SQLT_VNU, // Oracle type
|
|
SQLCS_IMPLICIT, // charset form
|
|
sizeof(OCINumber), // element length
|
|
0, // is character data
|
|
0, // is variable length
|
|
1, // can be copied
|
|
1 // can be in array
|
|
};
|
|
|
|
|
|
#ifdef SQLT_BFLOAT
|
|
static udt_VariableType vt_NativeFloat = {
|
|
(InitializeProc) NULL,
|
|
(FinalizeProc) NULL,
|
|
(PreDefineProc) NULL,
|
|
(PostDefineProc) NULL,
|
|
(PreFetchProc) NULL,
|
|
(IsNullProc) NULL,
|
|
(SetValueProc) NativeFloatVar_SetValue,
|
|
(GetValueProc) NativeFloatVar_GetValue,
|
|
(GetBufferSizeProc) NULL,
|
|
&g_NativeFloatVarType, // Python type
|
|
SQLT_BDOUBLE, // Oracle type
|
|
SQLCS_IMPLICIT, // charset form
|
|
sizeof(double), // element length
|
|
0, // is character data
|
|
0, // is variable length
|
|
1, // can be copied
|
|
1 // can be in array
|
|
};
|
|
#endif
|
|
|
|
|
|
#if PY_MAJOR_VERSION < 3
|
|
static udt_VariableType vt_Integer = {
|
|
(InitializeProc) NULL,
|
|
(FinalizeProc) NULL,
|
|
(PreDefineProc) NumberVar_PreDefine,
|
|
(PostDefineProc) NULL,
|
|
(PreFetchProc) NULL,
|
|
(IsNullProc) NULL,
|
|
(SetValueProc) NumberVar_SetValue,
|
|
(GetValueProc) NumberVar_GetValue,
|
|
(GetBufferSizeProc) NULL,
|
|
&g_NumberVarType, // Python type
|
|
SQLT_VNU, // Oracle type
|
|
SQLCS_IMPLICIT, // charset form
|
|
sizeof(OCINumber), // element length
|
|
0, // is character data
|
|
0, // is variable length
|
|
1, // can be copied
|
|
1 // can be in array
|
|
};
|
|
#endif
|
|
|
|
|
|
static udt_VariableType vt_LongInteger = {
|
|
(InitializeProc) NULL,
|
|
(FinalizeProc) NULL,
|
|
(PreDefineProc) NumberVar_PreDefine,
|
|
(PostDefineProc) NULL,
|
|
(PreFetchProc) NULL,
|
|
(IsNullProc) NULL,
|
|
(SetValueProc) NumberVar_SetValue,
|
|
(GetValueProc) NumberVar_GetValue,
|
|
(GetBufferSizeProc) NULL,
|
|
&g_NumberVarType, // Python type
|
|
SQLT_VNU, // Oracle type
|
|
SQLCS_IMPLICIT, // charset form
|
|
sizeof(OCINumber), // element length
|
|
0, // is character data
|
|
0, // is variable length
|
|
1, // can be copied
|
|
1 // can be in array
|
|
};
|
|
|
|
|
|
static udt_VariableType vt_NumberAsString = {
|
|
(InitializeProc) NULL,
|
|
(FinalizeProc) NULL,
|
|
(PreDefineProc) NumberVar_PreDefine,
|
|
(PostDefineProc) NULL,
|
|
(PreFetchProc) NULL,
|
|
(IsNullProc) NULL,
|
|
(SetValueProc) NumberVar_SetValue,
|
|
(GetValueProc) NumberVar_GetValue,
|
|
(GetBufferSizeProc) NULL,
|
|
&g_NumberVarType, // Python type
|
|
SQLT_VNU, // Oracle type
|
|
SQLCS_IMPLICIT, // charset form
|
|
sizeof(OCINumber), // element length
|
|
0, // is character data
|
|
0, // is variable length
|
|
1, // can be copied
|
|
1 // can be in array
|
|
};
|
|
|
|
|
|
static udt_VariableType vt_Boolean = {
|
|
(InitializeProc) NULL,
|
|
(FinalizeProc) NULL,
|
|
(PreDefineProc) NumberVar_PreDefine,
|
|
(PostDefineProc) NULL,
|
|
(PreFetchProc) NULL,
|
|
(IsNullProc) NULL,
|
|
(SetValueProc) NumberVar_SetValue,
|
|
(GetValueProc) NumberVar_GetValue,
|
|
(GetBufferSizeProc) NULL,
|
|
&g_NumberVarType, // Python type
|
|
SQLT_VNU, // Oracle type
|
|
SQLCS_IMPLICIT, // charset form
|
|
sizeof(OCINumber), // element length
|
|
0, // is character data
|
|
0, // is variable length
|
|
1, // can be copied
|
|
1 // can be in array
|
|
};
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// NumberVar_PreDefine()
|
|
// Set the type of value (integer, float or string) that will be returned
|
|
// when values are fetched from this variable.
|
|
//-----------------------------------------------------------------------------
|
|
static int NumberVar_PreDefine(
|
|
udt_NumberVar *var, // variable to initialize
|
|
OCIParam *param) // parameter handle
|
|
{
|
|
sb2 precision;
|
|
sword status;
|
|
sb1 scale;
|
|
|
|
// if the return type has not already been specified, check to see if the
|
|
// number can fit inside an integer by looking at the precision and scale
|
|
if (var->type == &vt_Float) {
|
|
scale = 0;
|
|
precision = 0;
|
|
status = OCIAttrGet(param, OCI_HTYPE_DESCRIBE, (dvoid*) &scale, 0,
|
|
OCI_ATTR_SCALE, var->environment->errorHandle);
|
|
if (Environment_CheckForError(var->environment, status,
|
|
"NumberVar_PreDefine(): scale") < 0)
|
|
return -1;
|
|
status = OCIAttrGet(param, OCI_HTYPE_DESCRIBE, (dvoid*) &precision, 0,
|
|
OCI_ATTR_PRECISION, var->environment->errorHandle);
|
|
if (Environment_CheckForError(var->environment, status,
|
|
"NumberVar_PreDefine(): precision") < 0)
|
|
return -1;
|
|
if (scale == 0 || (scale == -127 && precision == 0)) {
|
|
var->type = &vt_LongInteger;
|
|
#if PY_MAJOR_VERSION < 3
|
|
if (precision > 0 && precision < 10)
|
|
var->type = &vt_Integer;
|
|
#endif
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// NumberVar_SetValueFromBoolean()
|
|
// Set the value of the variable from a Python boolean.
|
|
//-----------------------------------------------------------------------------
|
|
static int NumberVar_SetValueFromBoolean(
|
|
udt_NumberVar *var, // variable to set value for
|
|
unsigned pos, // array position to set
|
|
PyObject *value) // value to set
|
|
{
|
|
long integerValue;
|
|
sword status;
|
|
|
|
integerValue = (value == Py_True);
|
|
status = OCINumberFromInt(var->environment->errorHandle, &integerValue,
|
|
sizeof(long), OCI_NUMBER_SIGNED, &var->data[pos]);
|
|
return Environment_CheckForError(var->environment, status,
|
|
"NumberVar_SetValueFromBoolean()");
|
|
}
|
|
|
|
|
|
#if PY_MAJOR_VERSION < 3
|
|
//-----------------------------------------------------------------------------
|
|
// NumberVar_SetValueFromInteger()
|
|
// Set the value of the variable from a Python integer.
|
|
//-----------------------------------------------------------------------------
|
|
static int NumberVar_SetValueFromInteger(
|
|
udt_NumberVar *var, // variable to set value for
|
|
unsigned pos, // array position to set
|
|
PyObject *value) // value to set
|
|
{
|
|
long integerValue;
|
|
sword status;
|
|
|
|
integerValue = PyInt_AS_LONG(value);
|
|
status = OCINumberFromInt(var->environment->errorHandle, &integerValue,
|
|
sizeof(long), OCI_NUMBER_SIGNED, &var->data[pos]);
|
|
return Environment_CheckForError(var->environment, status,
|
|
"NumberVar_SetValueFromInteger()");
|
|
}
|
|
#endif
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// NumberVar_SetValueFromFloat()
|
|
// Set the value of the variable from a Python float.
|
|
//-----------------------------------------------------------------------------
|
|
static int NumberVar_SetValueFromFloat(
|
|
udt_NumberVar *var, // variable to set value for
|
|
unsigned pos, // array position to set
|
|
PyObject *value) // value to set
|
|
{
|
|
double doubleValue;
|
|
sword status;
|
|
|
|
doubleValue = PyFloat_AS_DOUBLE(value);
|
|
status = OCINumberFromReal(var->environment->errorHandle, &doubleValue,
|
|
sizeof(double), &var->data[pos]);
|
|
return Environment_CheckForError(var->environment, status,
|
|
"NumberVar_SetValueFromFloat()");
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// NumberVar_SetValueFromLong()
|
|
// Set the value of the variable from a Python long.
|
|
//-----------------------------------------------------------------------------
|
|
static int NumberVar_SetValueFromLong(
|
|
udt_NumberVar *var, // variable to set value for
|
|
unsigned pos, // array position to set
|
|
PyObject *value) // value to set
|
|
{
|
|
udt_Buffer textBuffer;
|
|
PyObject *textValue;
|
|
sword status;
|
|
|
|
textValue = PyObject_Str(value);
|
|
if (!textValue)
|
|
return -1;
|
|
if (cxBuffer_FromObject(&textBuffer, textValue,
|
|
var->environment->encoding) < 0)
|
|
return -1;
|
|
status = OCINumberFromText(var->environment->errorHandle,
|
|
(text*) textBuffer.ptr, textBuffer.size,
|
|
(text*) var->environment->numberFromStringFormatBuffer.ptr,
|
|
var->environment->numberFromStringFormatBuffer.size, NULL, 0,
|
|
&var->data[pos]);
|
|
cxBuffer_Clear(&textBuffer);
|
|
Py_DECREF(textValue);
|
|
return Environment_CheckForError(var->environment, status,
|
|
"NumberVar_SetValueFromLong()");
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// NumberVar_GetFormatAndTextFromDecimal()
|
|
// Return the number format and text to use for the Decimal object.
|
|
//-----------------------------------------------------------------------------
|
|
static int NumberVar_GetFormatAndTextFromDecimal(
|
|
PyObject *tupleValue, // decimal as_tuple() value
|
|
PyObject **textObj, // text string for conversion
|
|
PyObject **formatObj) // format for conversion
|
|
{
|
|
long numDigits, scale, i, sign, length, digit;
|
|
char *textValue, *format, *textPtr, *formatPtr;
|
|
PyObject *digits;
|
|
|
|
// acquire basic information from the value tuple
|
|
sign = PyInt_AsLong(PyTuple_GET_ITEM(tupleValue, 0));
|
|
if (PyErr_Occurred())
|
|
return -1;
|
|
digits = PyTuple_GET_ITEM(tupleValue, 1);
|
|
scale = PyInt_AsLong(PyTuple_GET_ITEM(tupleValue, 2));
|
|
if (PyErr_Occurred())
|
|
return -1;
|
|
numDigits = PyTuple_GET_SIZE(digits);
|
|
|
|
// allocate memory for the string and format to use in conversion
|
|
length = numDigits + abs(scale) + 3;
|
|
textValue = textPtr = PyMem_Malloc(length);
|
|
if (!textValue) {
|
|
PyErr_NoMemory();
|
|
return -1;
|
|
}
|
|
format = formatPtr = PyMem_Malloc(length);
|
|
if (!format) {
|
|
PyMem_Free(textValue);
|
|
PyErr_NoMemory();
|
|
return -1;
|
|
}
|
|
|
|
// populate the string and format
|
|
if (sign)
|
|
*textPtr++ = '-';
|
|
for (i = 0; i < numDigits + scale; i++) {
|
|
*formatPtr++ = '9';
|
|
if (i < numDigits) {
|
|
digit = PyInt_AsLong(PyTuple_GetItem(digits, i));
|
|
if (PyErr_Occurred()) {
|
|
PyMem_Free(textValue);
|
|
return -1;
|
|
}
|
|
}
|
|
else digit = 0;
|
|
*textPtr++ = '0' + (char) digit;
|
|
}
|
|
if (scale < 0) {
|
|
*formatPtr++ = 'D';
|
|
*textPtr++ = '.';
|
|
for (i = scale; i < 0; i++) {
|
|
*formatPtr++ = '9';
|
|
if (numDigits + i < 0)
|
|
digit = 0;
|
|
else {
|
|
digit = PyInt_AsLong(PyTuple_GetItem(digits, numDigits + i));
|
|
if (PyErr_Occurred()) {
|
|
PyMem_Free(textValue);
|
|
return -1;
|
|
}
|
|
}
|
|
*textPtr++ = '0' + (char) digit;
|
|
}
|
|
}
|
|
*formatPtr = '\0';
|
|
*textPtr = '\0';
|
|
*textObj = cxString_FromAscii(textValue);
|
|
PyMem_Free(textValue);
|
|
if (!*textObj) {
|
|
PyMem_Free(format);
|
|
return -1;
|
|
}
|
|
*formatObj = cxString_FromAscii(format);
|
|
PyMem_Free(format);
|
|
if (!*formatObj) {
|
|
Py_DECREF(*textObj);
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// NumberVar_SetValueFromDecimal()
|
|
// Set the value of the variable from a Python decimal.Decimal object.
|
|
//-----------------------------------------------------------------------------
|
|
static int NumberVar_SetValueFromDecimal(
|
|
udt_NumberVar *var, // variable to set value for
|
|
unsigned pos, // array position to set
|
|
PyObject *value) // value to set
|
|
{
|
|
PyObject *textValue, *format, *tupleValue;
|
|
udt_Buffer textBuffer, formatBuffer;
|
|
sword status;
|
|
|
|
tupleValue = PyObject_CallMethod(value, "as_tuple", NULL);
|
|
if (!tupleValue)
|
|
return -1;
|
|
if (NumberVar_GetFormatAndTextFromDecimal(tupleValue, &textValue,
|
|
&format) < 0) {
|
|
Py_DECREF(tupleValue);
|
|
return -1;
|
|
}
|
|
Py_DECREF(tupleValue);
|
|
if (cxBuffer_FromObject(&textBuffer, textValue,
|
|
var->environment->encoding) < 0)
|
|
return -1;
|
|
if (cxBuffer_FromObject(&formatBuffer, format,
|
|
var->environment->encoding) < 0) {
|
|
cxBuffer_Clear(&textBuffer);
|
|
return -1;
|
|
}
|
|
status = OCINumberFromText(var->environment->errorHandle,
|
|
(text*) textBuffer.ptr, textBuffer.size, (text*) formatBuffer.ptr,
|
|
formatBuffer.size,
|
|
var->environment->nlsNumericCharactersBuffer.ptr,
|
|
var->environment->nlsNumericCharactersBuffer.size,
|
|
&var->data[pos]);
|
|
cxBuffer_Clear(&textBuffer);
|
|
cxBuffer_Clear(&formatBuffer);
|
|
Py_DECREF(textValue);
|
|
Py_DECREF(format);
|
|
return Environment_CheckForError(var->environment, status,
|
|
"NumberVar_SetValueFromDecimal()");
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// NumberVar_SetValue()
|
|
// Set the value of the variable.
|
|
//-----------------------------------------------------------------------------
|
|
static int NumberVar_SetValue(
|
|
udt_NumberVar *var, // variable to set value for
|
|
unsigned pos, // array position to set
|
|
PyObject *value) // value to set
|
|
{
|
|
#if PY_MAJOR_VERSION < 3
|
|
if (PyInt_Check(value))
|
|
return NumberVar_SetValueFromInteger(var, pos, value);
|
|
#endif
|
|
if (PyLong_Check(value))
|
|
return NumberVar_SetValueFromLong(var, pos, value);
|
|
if (PyBool_Check(value))
|
|
return NumberVar_SetValueFromBoolean(var, pos, value);
|
|
if (PyFloat_Check(value))
|
|
return NumberVar_SetValueFromFloat(var, pos, value);
|
|
if (Py_TYPE(value) == g_DecimalType)
|
|
return NumberVar_SetValueFromDecimal(var, pos, value);
|
|
PyErr_SetString(PyExc_TypeError, "expecting numeric data");
|
|
return -1;
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// NumberVar_GetValue()
|
|
// Returns the value stored at the given array position.
|
|
//-----------------------------------------------------------------------------
|
|
static PyObject *NumberVar_GetValue(
|
|
udt_NumberVar *var, // variable to determine value for
|
|
unsigned pos) // array position
|
|
{
|
|
PyObject *result, *stringObj;
|
|
char stringValue[200];
|
|
long integerValue;
|
|
ub4 stringLength;
|
|
sword status;
|
|
|
|
#if PY_MAJOR_VERSION < 3
|
|
if (var->type == &vt_Integer || var->type == &vt_Boolean) {
|
|
#else
|
|
if (var->type == &vt_Boolean) {
|
|
#endif
|
|
status = OCINumberToInt(var->environment->errorHandle, &var->data[pos],
|
|
sizeof(long), OCI_NUMBER_SIGNED, (dvoid*) &integerValue);
|
|
if (Environment_CheckForError(var->environment, status,
|
|
"NumberVar_GetValue(): as integer") < 0)
|
|
return NULL;
|
|
#if PY_MAJOR_VERSION < 3
|
|
if (var->type == &vt_Integer)
|
|
return PyInt_FromLong(integerValue);
|
|
#endif
|
|
return PyBool_FromLong(integerValue);
|
|
}
|
|
|
|
if (var->type == &vt_NumberAsString || var->type == &vt_LongInteger) {
|
|
stringLength = sizeof(stringValue);
|
|
status = OCINumberToText(var->environment->errorHandle,
|
|
&var->data[pos],
|
|
(text*) var->environment->numberToStringFormatBuffer.ptr,
|
|
var->environment->numberToStringFormatBuffer.size, NULL, 0,
|
|
&stringLength, (unsigned char*) stringValue);
|
|
if (Environment_CheckForError(var->environment, status,
|
|
"NumberVar_GetValue(): as string") < 0)
|
|
return NULL;
|
|
stringObj = cxString_FromEncodedString(stringValue, stringLength,
|
|
var->environment->encoding);
|
|
if (!stringObj)
|
|
return NULL;
|
|
if (var->type == &vt_NumberAsString)
|
|
return stringObj;
|
|
#if PY_MAJOR_VERSION >= 3
|
|
result = PyNumber_Long(stringObj);
|
|
#else
|
|
result = PyNumber_Int(stringObj);
|
|
#endif
|
|
Py_DECREF(stringObj);
|
|
if (result || !PyErr_ExceptionMatches(PyExc_ValueError))
|
|
return result;
|
|
PyErr_Clear();
|
|
}
|
|
|
|
return OracleNumberToPythonFloat(var->environment, &var->data[pos]);
|
|
}
|
|
|
|
|
|
#ifdef SQLT_BFLOAT
|
|
//-----------------------------------------------------------------------------
|
|
// NativeFloatVar_GetValue()
|
|
// Returns the value stored at the given array position as a float.
|
|
//-----------------------------------------------------------------------------
|
|
static PyObject *NativeFloatVar_GetValue(
|
|
udt_NativeFloatVar *var, // variable to determine value for
|
|
unsigned pos) // array position
|
|
{
|
|
return PyFloat_FromDouble(var->data[pos]);
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// NativeFloatVar_SetValue()
|
|
// Set the value of the variable which should be a native double.
|
|
//-----------------------------------------------------------------------------
|
|
static int NativeFloatVar_SetValue(
|
|
udt_NativeFloatVar *var, // variable to set value for
|
|
unsigned pos, // array position to set
|
|
PyObject *value) // value to set
|
|
{
|
|
if (!PyFloat_Check(value)) {
|
|
PyErr_SetString(PyExc_TypeError, "expecting float");
|
|
return -1;
|
|
}
|
|
var->data[pos] = PyFloat_AS_DOUBLE(value);
|
|
return 0;
|
|
}
|
|
#endif
|
|
|