// -*- Mode: C++; -*-
// Package : omniORBpy
// pyFixed.cc Created on: 2001/03/30
// Author : Duncan Grisby (dpg1)
//
// Copyright (C) 2001 AT&T Laboratories Cambridge
//
// This file is part of the omniORBpy library
//
// The omniORBpy library is free software; you can redistribute it
// and/or modify it under the terms of the GNU Lesser General
// Public License as published by the Free Software Foundation;
// either version 2.1 of the License, or (at your option) any later
// version.
//
// This library 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 Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free
// Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
// MA 02111-1307, USA
//
//
// Description:
// Implementation of Fixed type for Python
// $Id: pyFixed.cc,v 1.1.4.2 2005/01/07 00:22:32 dgrisby Exp $
// $Log: pyFixed.cc,v $
// Revision 1.1.4.2 2005/01/07 00:22:32 dgrisby
// Big merge from omnipy2_develop.
//
// Revision 1.1.4.1 2003/03/23 21:51:57 dgrisby
// New omnipy3_develop branch.
//
// Revision 1.1.2.6 2003/03/14 15:29:22 dgrisby
// Remove const char* -> char* warnings.
//
// Revision 1.1.2.5 2003/03/02 19:12:56 dgrisby
// Remove unnecessary #include.
//
// Revision 1.1.2.4 2001/09/24 10:48:26 dpg1
// Meaningful minor codes.
//
// Revision 1.1.2.3 2001/05/14 12:47:21 dpg1
// Fix memory leaks.
//
// Revision 1.1.2.2 2001/04/12 11:11:49 dpg1
// Can now construct a fixed point object given another one.
//
// Revision 1.1.2.1 2001/04/09 15:22:15 dpg1
// Fixed point support.
//
#include <omnipy.h>
#include <pyFixed.h>
#include <stdio.h>
static PyObject*
fixedValueAsPyLong(const CORBA::Fixed& f)
{
CORBA::String_var str = f.NP_asString();
// Seek out and destroy any decimal point
char* c;
for (c = (char*)str; *c && *c != '.'; ++c);
if (*c == '.') {
for (; *c; ++c)
*c = *(c+1);
}
return PyLong_FromString((char*)str, 0, 10);
}
PyObject*
omniPy::newFixedObject(const CORBA::Fixed& f)
{
omnipyFixedObject* pyf = PyMem_NEW(omnipyFixedObject, 1);
pyf->ob_type = &omnipyFixed_Type;
pyf->ob_fixed = new CORBA::Fixed(f);
_Py_NewReference((PyObject*)pyf);
return (PyObject*)pyf;
}
PyObject*
omniPy::newFixedObject(PyObject* self, PyObject* args)
{
try {
int size = PyTuple_Size(args);
if (size == 1) {
PyObject* pyv = PyTuple_GetItem(args, 0);
if (PyString_Check(pyv)) {
CORBA::Fixed f(PyString_AsString(pyv));
return omniPy::newFixedObject(f);
}
else if (PyInt_Check(pyv)) {
long l = PyInt_AsLong(pyv);
CORBA::Fixed f(l);
return omniPy::newFixedObject(f);
}
else if (PyLong_Check(pyv)) {
PyObject* pystr = PyObject_Str(pyv);
omniPy::PyRefHolder pystr_holder(pystr);
CORBA::Fixed f;
f.NP_fromString(PyString_AsString(pystr), 1);
return omniPy::newFixedObject(f);
}
else if (omnipyFixed_Check(pyv)) {
return omniPy::newFixedObject(*((omnipyFixedObject*)pyv)->ob_fixed);
}
}
else if (size == 3) {
PyObject* pyd = PyTuple_GetItem(args, 0);
PyObject* pys = PyTuple_GetItem(args, 1);
PyObject* pyv = PyTuple_GetItem(args, 2);
if (PyInt_Check(pyd) && PyInt_Check(pys)) {
long digits = PyInt_AsLong(pyd);
long scale = PyInt_AsLong(pys);
if (digits < 0 || digits > 31)
OMNIORB_THROW(DATA_CONVERSION,
DATA_CONVERSION_RangeError,
CORBA::COMPLETED_NO);
if (scale < 0 || scale > digits)
OMNIORB_THROW(DATA_CONVERSION,
DATA_CONVERSION_RangeError,
CORBA::COMPLETED_NO);
// The standard interface to fixed creation provides an int or
// long representing the required value of the fixed times
// 10**scale. We first convert the int/long into a Fixed with
// an integer value, then hack the scale to be correct.
if (PyInt_Check(pyv)) {
long l = PyInt_AsLong(pyv);
CORBA::Fixed f(l);
f.PR_changeScale(scale);
f.PR_setLimits(digits, scale);
return omniPy::newFixedObject(f);
}
else if (PyLong_Check(pyv)) {
PyObject* pystr = PyObject_Str(pyv);
omniPy::PyRefHolder pystr_holder(pystr);
CORBA::Fixed f;
f.NP_fromString(PyString_AsString(pystr), 1);
f.PR_changeScale(scale);
f.PR_setLimits(digits, scale);
return omniPy::newFixedObject(f);
}
else if (PyString_Check(pyv)) {
CORBA::Fixed f(PyString_AsString(pyv));
f.PR_setLimits(digits, scale);
return omniPy::newFixedObject(f);
}
else if (omnipyFixed_Check(pyv)) {
CORBA::Fixed f(*((omnipyFixedObject*)pyv)->ob_fixed);
f.PR_setLimits(digits, scale);
return omniPy::newFixedObject(f);
}
}
}
}
OMNIPY_CATCH_AND_HANDLE_SYSTEM_EXCEPTIONS
PyErr_SetString(PyExc_TypeError,
"incorrect arguments; see docstring for details.");
return 0;
}
extern "C" {
static void
fixed_dealloc(omnipyFixedObject* f)
{
delete f->ob_fixed;
PyMem_DEL(f);
}
static int
fixed_print(omnipyFixedObject* f, FILE* fp, int flags)
{
CORBA::String_var str = f->ob_fixed->NP_asString();
fputs((const char*)str, fp);
return 0;
}
static PyObject*
fixed_value(omnipyFixedObject* self, PyObject* args)
{
if (!PyArg_NoArgs(args)) return 0;
return fixedValueAsPyLong(*(self->ob_fixed));
}
static PyObject*
fixed_precision(omnipyFixedObject* self, PyObject* args)
{
if (!PyArg_NoArgs(args)) return 0;
return PyInt_FromLong(self->ob_fixed->fixed_digits());
}
static PyObject*
fixed_decimals(omnipyFixedObject* self, PyObject* args)
{
if (!PyArg_NoArgs(args)) return 0;
return PyInt_FromLong(self->ob_fixed->fixed_scale());
}
static PyObject*
fixed_round(omnipyFixedObject* self, PyObject* args)
{
int scale;
if (!PyArg_ParseTuple(args, (char*)"i", &scale)) return 0;
try {
CORBA::Fixed f(((omnipyFixedObject*)self)->ob_fixed->round(scale));
return omniPy::newFixedObject(f);
}
OMNIPY_CATCH_AND_HANDLE_SYSTEM_EXCEPTIONS
}
static PyObject*
fixed_truncate(omnipyFixedObject* self, PyObject* args)
{
int scale;
if (!PyArg_ParseTuple(args, (char*)"i", &scale)) return 0;
try {
CORBA::Fixed f(((omnipyFixedObject*)self)->ob_fixed->truncate(scale));
return omniPy::newFixedObject(f);
}
OMNIPY_CATCH_AND_HANDLE_SYSTEM_EXCEPTIONS
}
static PyMethodDef fixed_methods[] = {
{(char*)"value", (PyCFunction)fixed_value},
{(char*)"precision", (PyCFunction)fixed_precision},
{(char*)"decimals", (PyCFunction)fixed_decimals},
{(char*)"round", (PyCFunction)fixed_round, METH_VARARGS},
{(char*)"truncate", (PyCFunction)fixed_truncate, METH_VARARGS},
{0,0}
};
static PyObject*
fixed_getattr(omnipyFixedObject* f, char* name)
{
return Py_FindMethod(fixed_methods, (PyObject*) f, name);
}
static int
fixed_compare(omnipyFixedObject* a, omnipyFixedObject* b)
{
return CORBA::Fixed::NP_cmp(*(a->ob_fixed), *(b->ob_fixed));
}
static PyObject*
fixed_repr(omnipyFixedObject* f)
{
CORBA::String_var str = f->ob_fixed->NP_asString();
CORBA::String_var repr = CORBA::string_alloc(strlen(str) + 10);
sprintf((char*)repr, "fixed(\"%s\")", (const char*)str);
return PyString_FromString((const char*)repr);
}
static long
fixed_hash(omnipyFixedObject* f)
{
// Calculate the hash value by converting the digits to a Python
// long and finding its hash. Then rotate the result left by the
// fixed scale. This means that integer values hash to the same
// value as normal Python integers or longs.
long h;
PyObject* pyl = fixedValueAsPyLong(*(f->ob_fixed));
h = PyObject_Hash(pyl);
Py_DECREF(pyl);
unsigned long u = h;
int shift = f->ob_fixed->fixed_scale();
h = u << shift + u >> (32 - shift);
if (h == -1)
h = -2;
return h;
}
static PyObject*
fixed_str(omnipyFixedObject* f)
{
CORBA::String_var str = f->ob_fixed->NP_asString();
return PyString_FromString((const char*)str);
}
static PyObject*
fixed_add(omnipyFixedObject* a, omnipyFixedObject* b)
{
try {
return omniPy::newFixedObject(*a->ob_fixed + *b->ob_fixed);
}
OMNIPY_CATCH_AND_HANDLE_SYSTEM_EXCEPTIONS
}
static PyObject*
fixed_sub(omnipyFixedObject* a, omnipyFixedObject* b)
{
try {
return omniPy::newFixedObject(*a->ob_fixed - *b->ob_fixed);
}
OMNIPY_CATCH_AND_HANDLE_SYSTEM_EXCEPTIONS
}
static PyObject*
fixed_mul(omnipyFixedObject* a, omnipyFixedObject* b)
{
try {
return omniPy::newFixedObject(*a->ob_fixed * *b->ob_fixed);
}
OMNIPY_CATCH_AND_HANDLE_SYSTEM_EXCEPTIONS
}
static PyObject*
fixed_div(omnipyFixedObject* a, omnipyFixedObject* b)
{
try {
return omniPy::newFixedObject(*a->ob_fixed / *b->ob_fixed);
}
OMNIPY_CATCH_AND_HANDLE_SYSTEM_EXCEPTIONS
}
static PyObject*
fixed_neg(omnipyFixedObject* f)
{
return omniPy::newFixedObject(- *f->ob_fixed);
}
static PyObject*
fixed_pos(omnipyFixedObject* f)
{
Py_INCREF(f);
return (PyObject*)f;
}
static PyObject*
fixed_abs(omnipyFixedObject* f)
{
if (*f->ob_fixed < CORBA::Fixed(0))
return fixed_neg(f);
else
return fixed_pos(f);
}
static int
fixed_nonzero(omnipyFixedObject* f)
{
return *f->ob_fixed != CORBA::Fixed(0);
}
static int
fixed_coerce(PyObject** pv, PyObject** pw)
{
if (PyInt_Check(*pw)) {
long l = PyInt_AsLong(*pw);
CORBA::Fixed f(l);
*pw = omniPy::newFixedObject(f);
Py_INCREF(*pv);
return 0;
}
else if (PyLong_Check(*pw)) {
PyObject* pystr = PyObject_Str(*pw);
try {
CORBA::Fixed f;
f.NP_fromString(PyString_AsString(pystr), 1);
*pw = omniPy::newFixedObject(f);
Py_DECREF(pystr);
}
catch (...) {
Py_DECREF(pystr);
return 1; // Can't coerce
}
Py_INCREF(*pv);
return 0;
}
return 1; // Can't coerce
}
static PyObject *
fixed_int(PyObject* v)
{
try {
#ifdef HAS_LongLong
CORBA::LongLong ll = *((omnipyFixedObject*)v)->ob_fixed;
if (ll > _CORBA_LONGLONG_CONST(2147483647) ||
ll < _CORBA_LONGLONG_CONST(-2147483648))
OMNIORB_THROW(DATA_CONVERSION,
DATA_CONVERSION_RangeError,
CORBA::COMPLETED_NO);
return PyInt_FromLong((long)ll);
#else
CORBA::Long l = *((omnipyFixedObject*)v)->ob_fixed;
return PyInt_FromLong((long)l);
#endif
}
OMNIPY_CATCH_AND_HANDLE_SYSTEM_EXCEPTIONS
}
static PyObject*
fixed_long(PyObject* v)
{
CORBA::Fixed f = ((omnipyFixedObject*)v)->ob_fixed->truncate(0);
return fixedValueAsPyLong(f);
}
static PyNumberMethods fixed_as_number = {
(binaryfunc) fixed_add, /*nb_add*/
(binaryfunc) fixed_sub, /*nb_subtract*/
(binaryfunc) fixed_mul, /*nb_multiply*/
(binaryfunc) fixed_div, /*nb_divide*/
0, /*nb_remainder*/
0, /*nb_divmod*/
0, /*nb_power*/
(unaryfunc) fixed_neg, /*nb_negative*/
(unaryfunc) fixed_pos, /*nb_positive*/
(unaryfunc) fixed_abs, /*nb_absolute*/
(inquiry) fixed_nonzero, /*nb_nonzero*/
0, /*nb_invert*/
0, /*nb_lshift*/
0, /*nb_rshift*/
0, /*nb_and*/
0, /*nb_xor*/
0, /*nb_or*/
(coercion) fixed_coerce, /*nb_coerce*/
(unaryfunc) fixed_int, /*nb_int*/
(unaryfunc) fixed_long, /*nb_long*/
0, /*nb_float*/
0, /*nb_oct*/
0, /*nb_hex*/
};
static char fixed_type_doc [] =
"CORBA fixed point type.\n"
"\n"
"Standard functions on fixed value f:\n"
"\n"
" f.value() -> Python long containing fixed value * 10**decimals\n"
" f.precision() -> Total number of decimal digits\n"
" f.decimals() -> Scale of the number. i.e. digits after the\n"
" decimal point\n"
"\n"
"omniORB extensions:\n"
"\n"
" str(f) -> Value as a string\n"
" f.round(scale) -> Value rounded to scale decimal places\n"
" f.truncate(scale) -> Value truncated to scale decimal places\n";
PyTypeObject omnipyFixed_Type = {
PyObject_HEAD_INIT(&PyType_Type)
0,
"omnipyFixed",
sizeof(omnipyFixedObject),
0,
(destructor) fixed_dealloc, /*tp_dealloc*/
(printfunc) fixed_print, /*tp_print*/
(getattrfunc)fixed_getattr, /*tp_getattr*/
0, /*tp_setattr*/
(cmpfunc) fixed_compare, /*tp_compare*/
(reprfunc) fixed_repr, /*tp_repr*/
&fixed_as_number, /*tp_as_number*/
0, /*tp_as_sequence*/
0, /*tp_as_mapping*/
(hashfunc) fixed_hash, /*tp_hash*/
0, /*tp_call*/
(reprfunc) fixed_str, /*tp_str*/
0, /*tp_getattro*/
0, /*tp_setattro*/
0, /*tp_as_buffer*/
0, /*tp_flags*/
fixed_type_doc, /*tp_doc*/
};
}
syntax highlighted by Code2HTML, v. 0.9.1