// Cyphesis Online RPG Server and AI Engine
// Copyright (C) 2000 Alistair Riddoch
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// 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, write to the Free Software Foundation,
// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
// $Id: Py_Operation.cpp,v 1.59 2007-07-30 18:12:51 alriddoch Exp $
#include "Py_Operation.h"
#include "Py_RootEntity.h"
#include "Py_Oplist.h"
#include "Py_Object.h"
#include "Py_Thing.h"
#include "common/log.h"
using Atlas::Message::Element;
using Atlas::Message::ListType;
using Atlas::Objects::Root;
using Atlas::Objects::Operation::RootOperation;
using Atlas::Objects::Entity::RootEntity;
/*
* Beginning of Operation section.
*
* This is a python type that wraps up operation objects from
* Atlas::Objects::Operation namespace.
*
*/
/*
* Beginning of Operation methods section.
*/
static PyObject * Operation_setSerialno(PyOperation * self, PyObject * py_sno)
{
#ifndef NDEBUG
if (!self->operation.isValid()) {
PyErr_SetString(PyExc_AssertionError,"NULL Operation in Operation.setSerialno");
return NULL;
}
#endif // NDEBUG
// Takes integer, returns none
if (!PyInt_CheckExact(py_sno)) {
PyErr_SetString(PyExc_TypeError, "serialno not an integer");
return NULL;
}
int serialno = PyInt_AsLong(py_sno);
self->operation->setSerialno(serialno);
Py_INCREF(Py_None);
return Py_None;
}
static PyObject * Operation_setRefno(PyOperation * self, PyObject * py_rno)
{
// Takes integer, returns none
#ifndef NDEBUG
if (!self->operation.isValid()) {
PyErr_SetString(PyExc_AssertionError,"NULL Operation in Operation.setRefno");
return NULL;
}
#endif // NDEBUG
if (!PyInt_CheckExact(py_rno)) {
PyErr_SetString(PyExc_TypeError, "refno not an integer");
return NULL;
}
int refno = PyInt_AsLong(py_rno);
self->operation->setRefno(refno);
Py_INCREF(Py_None);
return Py_None;
}
static PyObject * Operation_setFrom(PyOperation * self, PyObject * py_from)
{
// Takes string, returns none
#ifndef NDEBUG
if (!self->operation.isValid()) {
PyErr_SetString(PyExc_AssertionError,"NULL Operation in Operation.setFrom");
return NULL;
}
#endif // NDEBUG
if (!PyString_CheckExact(py_from)) {
PyErr_SetString(PyExc_TypeError, "from not a string");
return NULL;
}
char * from = PyString_AsString(py_from);
self->operation->setFrom(from);
Py_INCREF(Py_None);
return Py_None;
}
static PyObject * Operation_setTo(PyOperation * self, PyObject * py_to)
{
// Takes string, returns none
#ifndef NDEBUG
if (!self->operation.isValid()) {
PyErr_SetString(PyExc_AssertionError,"NULL Operation in Operation.setTo");
return NULL;
}
#endif // NDEBUG
if (!PyString_CheckExact(py_to)) {
PyErr_SetString(PyExc_TypeError, "to not a string");
return NULL;
}
char * to = PyString_AsString(py_to);
self->operation->setTo(to);
Py_INCREF(Py_None);
return Py_None;
}
static PyObject * Operation_setSeconds(PyOperation * self, PyObject * py_secs)
{
// Takes float, returns none
#ifndef NDEBUG
if (!self->operation.isValid()) {
PyErr_SetString(PyExc_AssertionError,"NULL Operation in Operation.setSeconds");
return NULL;
}
#endif // NDEBUG
if (!PyFloat_CheckExact(py_secs)) {
PyErr_SetString(PyExc_TypeError, "seconds not a float");
return NULL;
}
double seconds = PyFloat_AsDouble(py_secs);
self->operation->setSeconds(seconds);
Py_INCREF(Py_None);
return Py_None;
}
static PyObject * Operation_setFutureSeconds(PyOperation * self,
PyObject * py_fsecs)
{
// Takes float, returns none
#ifndef NDEBUG
if (!self->operation.isValid()) {
PyErr_SetString(PyExc_AssertionError,"NULL Operation in Operation.setFutureSeconds");
return NULL;
}
#endif // NDEBUG
double futureseconds = PyFloat_AsDouble(py_fsecs);
if (PyFloat_CheckExact(py_fsecs)) {
futureseconds = PyFloat_AsDouble(py_fsecs);
} else if (PyInt_CheckExact(py_fsecs)) {
futureseconds = PyInt_AsLong(py_fsecs);
} else {
PyErr_SetString(PyExc_TypeError, "future_seconds not a number");
return NULL;
}
self->operation->setFutureSeconds(futureseconds);
Py_INCREF(Py_None);
return Py_None;
}
static PyObject * Operation_setArgs(PyOperation * self, PyObject * args)
{
// Takes List, returns none
#ifndef NDEBUG
if (!self->operation.isValid()) {
PyErr_SetString(PyExc_AssertionError,"NULL Operation in Operation.setArgs");
return NULL;
}
#endif // NDEBUG
// FIXME This is a big mess - either get rid of it in entirity, or
// make something better.
if (!PyList_Check(args)) {
PyErr_SetString(PyExc_TypeError, "args not a list");
return NULL;
}
ListType argslist;
for(int i = 0; i < PyList_Size(args); i++) {
PyObject * item = PyList_GetItem(args, i);
if (PyMessageElement_Check(item)) {
argslist.push_back(*((PyMessageElement*)item)->m_obj);
} else if (PyOperation_Check(item)) {
argslist.push_back(((PyOperation*)item)->operation->asMessage());
} else {
PyErr_SetString(PyExc_TypeError,"args contains non Atlas Object");
return NULL;
}
}
self->operation->setArgsAsList(argslist);
Py_INCREF(Py_None);
return Py_None;
}
static PyObject * Operation_getSerialno(PyOperation * self)
{
// Returns int
#ifndef NDEBUG
if (!self->operation.isValid()) {
PyErr_SetString(PyExc_AssertionError,"NULL Operation in Operation.getSerialno");
return NULL;
}
#endif // NDEBUG
return PyInt_FromLong(self->operation->getSerialno());
}
static PyObject * Operation_getRefno(PyOperation * self)
{
// Returns int
#ifndef NDEBUG
if (!self->operation.isValid()) {
PyErr_SetString(PyExc_AssertionError,"NULL Operation in Operation.getRefno");
return NULL;
}
#endif // NDEBUG
return PyInt_FromLong(self->operation->getRefno());
}
static PyObject * Operation_getFrom(PyOperation * self)
{
// Returns string
#ifndef NDEBUG
if (!self->operation.isValid()) {
PyErr_SetString(PyExc_AssertionError,"NULL Operation in Operation.getFrom");
return NULL;
}
#endif // NDEBUG
return PyString_FromString(self->operation->getFrom().c_str());
}
static PyObject * Operation_getTo(PyOperation * self)
{
// Returns string
#ifndef NDEBUG
if (!self->operation.isValid()) {
PyErr_SetString(PyExc_AssertionError,"NULL Operation in Operation.getTo");
return NULL;
}
#endif // NDEBUG
return PyString_FromString(self->operation->getTo().c_str());
}
static PyObject * Operation_getSeconds(PyOperation * self)
{
// Returns float
#ifndef NDEBUG
if (!self->operation.isValid()) {
PyErr_SetString(PyExc_AssertionError,"NULL Operation in Operation.getSeconds");
return NULL;
}
#endif // NDEBUG
return PyFloat_FromDouble(self->operation->getSeconds());
}
static PyObject * Operation_getFutureSeconds(PyOperation * self)
{
// Returns float
#ifndef NDEBUG
if (!self->operation.isValid()) {
PyErr_SetString(PyExc_AssertionError,"NULL Operation in Operation.getFutureSeconds");
return NULL;
}
#endif // NDEBUG
return PyFloat_FromDouble(self->operation->getFutureSeconds());
}
static PyObject * Operation_getArgs(PyOperation * self)
{
// Returns list
#ifndef NDEBUG
if (!self->operation.isValid()) {
PyErr_SetString(PyExc_AssertionError,"NULL Operation in Operation.getArgs");
return NULL;
}
#endif // NDEBUG
// Here we go:-
// FIXME
// Here we need a generic way to make a Root object into a python object,
// either by wrapping as a Operation, or as an Entity. New Entity binding
// thus required. Once written this code should also be used in
// Operation_seq_item(), and the code there is a better starting point.
const std::vector<Root> & args_list = self->operation->getArgs();
PyObject * args_pylist = PyList_New(args_list.size());
int j = 0;
PyMessageElement * item;
std::vector<Root>::const_iterator Iend = args_list.end();
std::vector<Root>::const_iterator I = args_list.begin();
for (; I != Iend; ++I, ++j) {
item = newPyMessageElement();
if (item == NULL) {
PyErr_SetString(PyExc_TypeError,"error creating list");
Py_DECREF(args_pylist);
return NULL;
}
item->m_obj = new Element((*I)->asMessage());
PyList_SetItem(args_pylist, j, (PyObject *)item);
}
return args_pylist;
}
static PyObject* Operation_get_name(PyOperation * self)
{
#ifndef NDEBUG
if (!self->operation.isValid()) {
PyErr_SetString(PyExc_AssertionError,"NULL Operation in Operation.get_name");
return NULL;
}
#endif // NDEBUG
return PyString_FromString("op");
}
/*
* Operation sequence methods.
*/
#if PY_VERSION_HEX < 0x02050000
typedef int Py_ssize_t;
#endif
static Py_ssize_t Operation_seq_length(PyOperation * self)
{
#ifndef NDEBUG
if (!self->operation.isValid()) {
PyErr_SetString(PyExc_AssertionError,"NULL Operation in Operation.seq_length");
return 0;
}
#endif // NDEBUG
return self->operation->getArgs().size();
}
static PyObject * Operation_seq_item(PyOperation * self, Py_ssize_t item)
{
#ifndef NDEBUG
if (!self->operation.isValid()) {
PyErr_SetString(PyExc_AssertionError,"NULL Operation in Operation.seq_item");
return 0;
}
#endif // NDEBUG
const std::vector<Root> & args_list = self->operation->getArgs();
std::vector<Root>::const_iterator I = args_list.begin();
std::vector<Root>::const_iterator Iend = args_list.end();
for(int i = 0; i < item && I != Iend; ++i, ++I);
if (I == args_list.end()) {
PyErr_SetString(PyExc_TypeError,"Operation.[]: Not enought op arguments");
return 0;
}
const Root & arg = *I;
RootOperation op = Atlas::Objects::smart_dynamic_cast<RootOperation>(arg);
if (op.isValid()) {
PyOperation * ret_op = newPyOperation();
ret_op->operation = op;
return (PyObject *)ret_op;
}
RootEntity ent = Atlas::Objects::smart_dynamic_cast<RootEntity>(arg);
if (ent.isValid()) {
PyRootEntity * ret_ent = newPyRootEntity();
ret_ent->entity = ent;
return (PyObject *)ret_ent;
}
log(WARNING, "Non operation or entity being returned as arg of operation");
PyMessageElement * ret = newPyMessageElement();
ret->m_obj = new Element(arg->asMessage());
return (PyObject *)ret;
}
static PyObject * Operation_num_add(PyOperation *self, PyObject *other)
{
fflush(stdout);
#ifndef NDEBUG
if (!self->operation.isValid()) {
PyErr_SetString(PyExc_AssertionError, "NULL Operation in Operation.num_add");
fflush(stdout);
return NULL;
}
#endif // NDEBUG
if (other == Py_None) {
PyOplist * res = newPyOplist();
res->ops = new OpVector();
res->ops->push_back(self->operation);
fflush(stdout);
return (PyObject*)res;
}
if (PyOplist_Check(other)) {
PyOplist * opl = (PyOplist*)other;
if (opl->ops == NULL) {
PyErr_SetString(PyExc_AssertionError, "invalid OpVector");
return NULL;
}
PyOplist * res = newPyOplist();
if (res == NULL) {
return NULL;
}
res->ops = new OpVector(*opl->ops);
res->ops->push_back(self->operation);
fflush(stdout);
return (PyObject*)res;
}
if (PyOperation_Check(other)) {
PyOperation * op = (PyOperation*)other;
#ifndef NDEBUG
if (!op->operation.isValid()) {
PyErr_SetString(PyExc_AssertionError, "NULL Operation in other of Operation.num_add");
}
#endif // NDEBUG
PyOplist * res = newPyOplist();
if (res == NULL) {
return NULL;
}
res->ops = new OpVector();
res->ops->push_back(op->operation);
res->ops->push_back(self->operation);
fflush(stdout);
return (PyObject*)res;
}
fflush(stdout);
return NULL;
}
/*
* Operation numerical methods.
*/
static int Operation_num_coerce(PyObject ** self, PyObject ** other)
{
//if (*other == Py_None) {
Py_INCREF(*self);
Py_INCREF(*other);
return 0;
//}
//return -1;
}
/*
* Operation numerical methods structure.
*/
static PyNumberMethods Operation_num = {
(binaryfunc)Operation_num_add,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
Operation_num_coerce,
0,
0,
0,
0,
0
};
#if PY_MINOR_VERSION < 5
#define lenfunc inquiry
#define ssizeargfunc intargfunc
#endif
/*
* Operation sequence methods structure.
*/
static PySequenceMethods Operation_seq = {
(lenfunc)Operation_seq_length, /* sq_length */
NULL, /* sq_concat */
NULL, /* sq_repeat */
(ssizeargfunc)Operation_seq_item, /* sq_item */
NULL, /* sq_slice */
NULL, /* sq_ass_item */
NULL /* sq_ass_slice */
};
/*
* Operation methods structure.
*
* Generated from a macro in case we need one for each type of operation.
*
*/
PyMethodDef RootOperation_methods[] = {
{"setSerialno", (PyCFunction)Operation_setSerialno, METH_O},
{"setRefno", (PyCFunction)Operation_setRefno, METH_O},
{"setFrom", (PyCFunction)Operation_setFrom, METH_O},
{"setTo", (PyCFunction)Operation_setTo, METH_O},
{"setSeconds", (PyCFunction)Operation_setSeconds, METH_O},
{"setFutureSeconds",(PyCFunction)Operation_setFutureSeconds,METH_O},
{"setArgs", (PyCFunction)Operation_setArgs, METH_O},
{"getSerialno", (PyCFunction)Operation_getSerialno, METH_NOARGS},
{"getRefno", (PyCFunction)Operation_getRefno, METH_NOARGS},
{"getFrom", (PyCFunction)Operation_getFrom, METH_NOARGS},
{"getTo", (PyCFunction)Operation_getTo, METH_NOARGS},
{"getSeconds", (PyCFunction)Operation_getSeconds, METH_NOARGS},
{"getFutureSeconds",(PyCFunction)Operation_getFutureSeconds,METH_NOARGS},
{"getArgs", (PyCFunction)Operation_getArgs, METH_NOARGS},
{"get_name", (PyCFunction)Operation_get_name, METH_NOARGS},
{NULL, NULL}
};
PyMethodDef ConstRootOperation_methods[] = {
{"getSerialno", (PyCFunction)Operation_getSerialno, METH_NOARGS},
{"getRefno", (PyCFunction)Operation_getRefno, METH_NOARGS},
{"getFrom", (PyCFunction)Operation_getFrom, METH_NOARGS},
{"getTo", (PyCFunction)Operation_getTo, METH_NOARGS},
{"getSeconds", (PyCFunction)Operation_getSeconds, METH_NOARGS},
{"getFutureSeconds",(PyCFunction)Operation_getFutureSeconds,METH_NOARGS},
{"getArgs", (PyCFunction)Operation_getArgs, METH_NOARGS},
{"get_name", (PyCFunction)Operation_get_name, METH_NOARGS},
{NULL, NULL}
};
/*
* Beginning of Operation standard methods section.
*/
static void Operation_dealloc(PyOperation *self)
{
self->operation.~RootOperation();
PyObject_Free(self);
}
static inline PyObject * findMethod(PyOperation * self, char * name)
{
return Py_FindMethod(RootOperation_methods, (PyObject *)self, name);
}
static inline PyObject * findMethod(PyConstOperation * self, char * name)
{
return Py_FindMethod(ConstRootOperation_methods, (PyObject *)self, name);
}
template <typename T>
static PyObject * getattr(T * self, char * name)
{
#ifndef NDEBUG
if (!self->operation.isValid()) {
PyErr_SetString(PyExc_AssertionError, "NULL Operation in Operation.getattr");
return NULL;
}
#endif // NDEBUG
if (strcmp(name, "from_") == 0) {
return PyString_FromString(self->operation->getFrom().c_str());
} else if (strcmp(name, "to") == 0) {
return PyString_FromString(self->operation->getTo().c_str());
} else if (strcmp(name, "id") == 0) {
const std::list<std::string> & parents = self->operation->getParents();
if (parents.empty()) {
PyErr_SetString(PyExc_TypeError, "Operation has no parents");
return NULL;
}
return PyString_FromString(parents.front().c_str());
}
return findMethod(self, name);
}
static PyObject * Operation_getattr(PyOperation * self, char * name)
{
return getattr(self, name);
}
static PyObject * ConstOperation_getattr(PyConstOperation * self, char * name)
{
return getattr(self, name);
}
static int Operation_setattr(PyOperation *self, char *name, PyObject *v)
{
#ifndef NDEBUG
if (!self->operation.isValid()) {
PyErr_SetString(PyExc_AssertionError, "NULL Operation in Operation.setattr");
return -1;
}
#endif // NDEBUG
if (strcmp(name, "from_") == 0) {
PyObject * thing_id = PyObject_GetAttrString(v, "id");
if (thing_id == NULL || !PyString_Check(thing_id)) {
PyErr_SetString(PyExc_TypeError, "invalid from");
if (thing_id != NULL) {
Py_DECREF(thing_id);
}
return -1;
}
self->operation->setFrom(PyString_AsString(thing_id));
Py_DECREF(thing_id);
return 0;
}
if (strcmp(name, "to") == 0) {
PyObject * thing_id = PyObject_GetAttrString(v, "id");
if (thing_id == NULL || !PyString_Check(thing_id)) {
PyErr_SetString(PyExc_TypeError, "invalid to");
if (thing_id != NULL) {
Py_DECREF(thing_id);
}
return -1;
}
self->operation->setTo(PyString_AsString(thing_id));
Py_DECREF(thing_id);
return 0;
}
PyErr_SetString(PyExc_AttributeError, "unknown attribute");
return -1;
}
PyTypeObject PyOperation_Type = {
PyObject_HEAD_INIT(&PyType_Type)
0, // ob_size
"Operation", // tp_name
sizeof(PyOperation), // tp_basicsize
0, // tp_itemsize
// methods
(destructor)Operation_dealloc, // tp_dealloc
0, // tp_print
(getattrfunc)Operation_getattr, // tp_getattr
(setattrfunc)Operation_setattr, // tp_setattr
0, // tp_compare
0, // tp_repr
&Operation_num, // tp_as_number
&Operation_seq, // tp_as_sequence
0, // tp_as_mapping
0, // tp_hash
};
PyTypeObject PyConstOperation_Type = {
PyObject_HEAD_INIT(&PyType_Type)
0, // ob_size
"Operation", // tp_name
sizeof(PyConstOperation), // tp_basicsize
0, // tp_itemsize
// methods
(destructor)Operation_dealloc, // tp_dealloc
0, // tp_print
(getattrfunc)ConstOperation_getattr, // tp_getattr
0, // tp_setattr
0, // tp_compare
0, // tp_repr
&Operation_num, // tp_as_number
&Operation_seq, // tp_as_sequence
0, // tp_as_mapping
0, // tp_hash
};
/*
* Beginning of Operation creation functions section.
*/
PyOperation * newPyOperation()
{
PyOperation * self;
self = PyObject_NEW(PyOperation, &PyOperation_Type);
if (self == NULL) {
return NULL;
}
new (&(self->operation)) RootOperation(NULL);
return self;
}
PyConstOperation * newPyConstOperation()
{
PyConstOperation * self;
self = PyObject_NEW(PyConstOperation, &PyConstOperation_Type);
if (self == NULL) {
return NULL;
}
new (&(self->operation)) RootOperation(NULL);
return self;
}
syntax highlighted by Code2HTML, v. 0.9.1