1 //
2 // Copyright (c) ZeroC, Inc. All rights reserved.
3 //
4 
5 #include <Endpoint.h>
6 #include <EndpointInfo.h>
7 #include <Util.h>
8 
9 using namespace std;
10 using namespace IcePy;
11 
12 namespace IcePy
13 {
14 
15 struct EndpointObject
16 {
17     PyObject_HEAD
18     Ice::EndpointPtr* endpoint;
19 };
20 
21 }
22 
23 #ifdef WIN32
24 extern "C"
25 #endif
26 static EndpointObject*
endpointNew(PyTypeObject *,PyObject *,PyObject *)27 endpointNew(PyTypeObject* /*type*/, PyObject* /*args*/, PyObject* /*kwds*/)
28 {
29     PyErr_Format(PyExc_RuntimeError, STRCAST("An endpoint cannot be created directly"));
30     return 0;
31 }
32 
33 #ifdef WIN32
34 extern "C"
35 #endif
36 static void
endpointDealloc(EndpointObject * self)37 endpointDealloc(EndpointObject* self)
38 {
39     delete self->endpoint;
40     Py_TYPE(self)->tp_free(reinterpret_cast<PyObject*>(self));
41 }
42 
43 #ifdef WIN32
44 extern "C"
45 #endif
46 static PyObject*
endpointCompare(EndpointObject * p1,PyObject * other,int op)47 endpointCompare(EndpointObject* p1, PyObject* other, int op)
48 {
49     bool result = false;
50 
51     if(PyObject_TypeCheck(other, &EndpointType))
52     {
53         EndpointObject* p2 = reinterpret_cast<EndpointObject*>(other);
54 
55         switch(op)
56         {
57         case Py_EQ:
58             result = *p1->endpoint == *p2->endpoint;
59             break;
60         case Py_NE:
61             result = *p1->endpoint != *p2->endpoint;
62             break;
63         case Py_LE:
64             result = *p1->endpoint <= *p2->endpoint;
65             break;
66         case Py_GE:
67             result = *p1->endpoint >= *p2->endpoint;
68             break;
69         case Py_LT:
70             result = *p1->endpoint < *p2->endpoint;
71             break;
72         case Py_GT:
73             result = *p1->endpoint > *p2->endpoint;
74             break;
75         }
76     }
77     else
78     {
79         if(op == Py_EQ)
80         {
81             result = false;
82         }
83         else if(op == Py_NE)
84         {
85             result = true;
86         }
87         else
88         {
89             PyErr_Format(PyExc_TypeError, "can't compare %s to %s", Py_TYPE(p1)->tp_name, Py_TYPE(other)->tp_name);
90             return 0;
91         }
92     }
93 
94     return result ? incTrue() : incFalse();
95 }
96 
97 #ifdef WIN32
98 extern "C"
99 #endif
100 static PyObject*
endpointToString(EndpointObject * self,PyObject *)101 endpointToString(EndpointObject* self, PyObject* /*args*/)
102 {
103     assert(self->endpoint);
104     try
105     {
106         string str = (*self->endpoint)->toString();
107         return createString(str);
108     }
109     catch(const Ice::Exception& ex)
110     {
111         setPythonException(ex);
112         return 0;
113     }
114 }
115 
116 #ifdef WIN32
117 extern "C"
118 #endif
119 static PyObject*
endpointRepr(EndpointObject * self)120 endpointRepr(EndpointObject* self)
121 {
122     return endpointToString(self, 0);
123 }
124 
125 #ifdef WIN32
126 extern "C"
127 #endif
128 static PyObject*
endpointGetInfo(EndpointObject * self,PyObject *)129 endpointGetInfo(EndpointObject* self, PyObject* /*args*/)
130 {
131     assert(self->endpoint);
132     try
133     {
134         Ice::EndpointInfoPtr info = (*self->endpoint)->getInfo();
135         return createEndpointInfo(info);
136     }
137     catch(const Ice::Exception& ex)
138     {
139         setPythonException(ex);
140         return 0;
141     }
142 }
143 
144 static PyMethodDef EndpointMethods[] =
145 {
146     { STRCAST("toString"), reinterpret_cast<PyCFunction>(endpointToString), METH_NOARGS,
147         PyDoc_STR(STRCAST("toString() -> string")) },
148     { STRCAST("getInfo"), reinterpret_cast<PyCFunction>(endpointGetInfo), METH_NOARGS,
149         PyDoc_STR(STRCAST("getInfo() -> Ice.EndpointInfo")) },
150     { 0, 0 } /* sentinel */
151 };
152 
153 namespace IcePy
154 {
155 
156 PyTypeObject EndpointType =
157 {
158     /* The ob_type field must be initialized in the module init function
159      * to be portable to Windows without using C++. */
160     PyVarObject_HEAD_INIT(0, 0)
161     STRCAST("IcePy.Endpoint"),       /* tp_name */
162     sizeof(EndpointObject),          /* tp_basicsize */
163     0,                               /* tp_itemsize */
164     /* methods */
165     reinterpret_cast<destructor>(endpointDealloc), /* tp_dealloc */
166     0,                               /* tp_print */
167     0,                               /* tp_getattr */
168     0,                               /* tp_setattr */
169     0,                               /* tp_reserved */
170     reinterpret_cast<reprfunc>(endpointRepr), /* tp_repr */
171     0,                               /* tp_as_number */
172     0,                               /* tp_as_sequence */
173     0,                               /* tp_as_mapping */
174     0,                               /* tp_hash */
175     0,                               /* tp_call */
176     0,                               /* tp_str */
177     0,                               /* tp_getattro */
178     0,                               /* tp_setattro */
179     0,                               /* tp_as_buffer */
180 #if PY_VERSION_HEX >= 0x03000000
181     Py_TPFLAGS_DEFAULT |
182     Py_TPFLAGS_BASETYPE,             /* tp_flags */
183 #else
184     Py_TPFLAGS_DEFAULT |
185     Py_TPFLAGS_BASETYPE |
186     Py_TPFLAGS_HAVE_RICHCOMPARE,     /* tp_flags */
187 #endif
188     0,                               /* tp_doc */
189     0,                               /* tp_traverse */
190     0,                               /* tp_clear */
191     reinterpret_cast<richcmpfunc>(endpointCompare), /* tp_richcompare */
192     0,                               /* tp_weaklistoffset */
193     0,                               /* tp_iter */
194     0,                               /* tp_iternext */
195     EndpointMethods,                 /* tp_methods */
196     0,                               /* tp_members */
197     0,                               /* tp_getset */
198     0,                               /* tp_base */
199     0,                               /* tp_dict */
200     0,                               /* tp_descr_get */
201     0,                               /* tp_descr_set */
202     0,                               /* tp_dictoffset */
203     0,                               /* tp_init */
204     0,                               /* tp_alloc */
205     reinterpret_cast<newfunc>(endpointNew), /* tp_new */
206     0,                               /* tp_free */
207     0,                               /* tp_is_gc */
208 };
209 
210 };
211 
212 bool
initEndpoint(PyObject * module)213 IcePy::initEndpoint(PyObject* module)
214 {
215     if(PyType_Ready(&EndpointType) < 0)
216     {
217         return false;
218     }
219     PyTypeObject* type = &EndpointType; // Necessary to prevent GCC's strict-alias warnings.
220     if(PyModule_AddObject(module, STRCAST("Endpoint"), reinterpret_cast<PyObject*>(type)) < 0)
221     {
222         return false;
223     }
224 
225     return true;
226 }
227 
228 Ice::EndpointPtr
getEndpoint(PyObject * obj)229 IcePy::getEndpoint(PyObject* obj)
230 {
231     assert(PyObject_IsInstance(obj, reinterpret_cast<PyObject*>(&EndpointType)));
232     EndpointObject* eobj = reinterpret_cast<EndpointObject*>(obj);
233     return *eobj->endpoint;
234 }
235 
236 PyObject*
createEndpoint(const Ice::EndpointPtr & endpoint)237 IcePy::createEndpoint(const Ice::EndpointPtr& endpoint)
238 {
239     EndpointObject* obj = reinterpret_cast<EndpointObject*>(EndpointType.tp_alloc(&EndpointType, 0));
240     if(!obj)
241     {
242         return 0;
243     }
244     obj->endpoint = new Ice::EndpointPtr(endpoint);
245     return (PyObject*)obj;
246 }
247 
248 bool
toEndpointSeq(PyObject * endpoints,Ice::EndpointSeq & seq)249 IcePy::toEndpointSeq(PyObject* endpoints, Ice::EndpointSeq& seq)
250 {
251     Py_ssize_t sz = PySequence_Fast_GET_SIZE(endpoints);
252     for(Py_ssize_t i = 0; i < sz; ++i)
253     {
254         PyObject* p = PySequence_Fast_GET_ITEM(endpoints, i);
255         PyTypeObject* type = &EndpointType; // Necessary to prevent GCC's strict-alias warnings.
256         if(!PyObject_IsInstance(p, reinterpret_cast<PyObject*>(type)))
257         {
258             PyErr_Format(PyExc_ValueError, STRCAST("expected element of type Ice.Endpoint"));
259             return false;
260         }
261         Ice::EndpointPtr endp = getEndpoint(p);
262         if(!endp)
263         {
264             return false;
265         }
266         seq.push_back(endp);
267     }
268 
269     return true;
270 }
271