]> git.proxmox.com Git - mirror_edk2.git/blame - AppPkg/Applications/Python/Python-2.7.10/Modules/operator.c
EmbeddedPkg: Extend NvVarStoreFormattedLib LIBRARY_CLASS
[mirror_edk2.git] / AppPkg / Applications / Python / Python-2.7.10 / Modules / operator.c
CommitLineData
7eb75bcc
DM
1\r
2#include "Python.h"\r
3\r
4PyDoc_STRVAR(operator_doc,\r
5"Operator interface.\n\\r
6\n\\r
7This module exports a set of functions implemented in C corresponding\n\\r
8to the intrinsic operators of Python. For example, operator.add(x, y)\n\\r
9is equivalent to the expression x+y. The function names are those\n\\r
10used for special methods; variants without leading and trailing\n\\r
11'__' are also provided for convenience.");\r
12\r
13#define spam1(OP,AOP) static PyObject *OP(PyObject *s, PyObject *a1) { \\r
14 return AOP(a1); }\r
15\r
16#define spam2(OP,AOP) static PyObject *OP(PyObject *s, PyObject *a) { \\r
17 PyObject *a1, *a2; \\r
18 if(! PyArg_UnpackTuple(a,#OP,2,2,&a1,&a2)) return NULL; \\r
19 return AOP(a1,a2); }\r
20\r
21#define spamoi(OP,AOP) static PyObject *OP(PyObject *s, PyObject *a) { \\r
22 PyObject *a1; int a2; \\r
23 if(! PyArg_ParseTuple(a,"Oi:" #OP,&a1,&a2)) return NULL; \\r
24 return AOP(a1,a2); }\r
25\r
26#define spam2n(OP,AOP) static PyObject *OP(PyObject *s, PyObject *a) { \\r
27 PyObject *a1, *a2; \\r
28 if(! PyArg_UnpackTuple(a,#OP,2,2,&a1,&a2)) return NULL; \\r
29 if(-1 == AOP(a1,a2)) return NULL; \\r
30 Py_INCREF(Py_None); \\r
31 return Py_None; }\r
32\r
33#define spam3n(OP,AOP) static PyObject *OP(PyObject *s, PyObject *a) { \\r
34 PyObject *a1, *a2, *a3; \\r
35 if(! PyArg_UnpackTuple(a,#OP,3,3,&a1,&a2,&a3)) return NULL; \\r
36 if(-1 == AOP(a1,a2,a3)) return NULL; \\r
37 Py_INCREF(Py_None); \\r
38 return Py_None; }\r
39\r
40#define spami(OP,AOP) static PyObject *OP(PyObject *s, PyObject *a1) { \\r
41 long r; \\r
42 if(-1 == (r=AOP(a1))) return NULL; \\r
43 return PyBool_FromLong(r); }\r
44\r
45#define spami2(OP,AOP) static PyObject *OP(PyObject *s, PyObject *a) { \\r
46 PyObject *a1, *a2; long r; \\r
47 if(! PyArg_UnpackTuple(a,#OP,2,2,&a1,&a2)) return NULL; \\r
48 if(-1 == (r=AOP(a1,a2))) return NULL; \\r
49 return PyInt_FromLong(r); }\r
50\r
51#define spamn2(OP,AOP) static PyObject *OP(PyObject *s, PyObject *a) { \\r
52 PyObject *a1, *a2; Py_ssize_t r; \\r
53 if(! PyArg_UnpackTuple(a,#OP,2,2,&a1,&a2)) return NULL; \\r
54 if(-1 == (r=AOP(a1,a2))) return NULL; \\r
55 return PyInt_FromSsize_t(r); }\r
56\r
57#define spami2b(OP,AOP) static PyObject *OP(PyObject *s, PyObject *a) { \\r
58 PyObject *a1, *a2; long r; \\r
59 if(! PyArg_UnpackTuple(a,#OP,2,2,&a1,&a2)) return NULL; \\r
60 if(-1 == (r=AOP(a1,a2))) return NULL; \\r
61 return PyBool_FromLong(r); }\r
62\r
63#define spamrc(OP,A) static PyObject *OP(PyObject *s, PyObject *a) { \\r
64 PyObject *a1, *a2; \\r
65 if(! PyArg_UnpackTuple(a,#OP,2,2,&a1,&a2)) return NULL; \\r
66 return PyObject_RichCompare(a1,a2,A); }\r
67\r
68/* Deprecated operators that need warnings. */\r
69static int\r
70op_isCallable(PyObject *x)\r
71{\r
72 if (PyErr_WarnPy3k("operator.isCallable() is not supported in 3.x. "\r
73 "Use hasattr(obj, '__call__').", 1) < 0)\r
74 return -1;\r
75 return PyCallable_Check(x);\r
76}\r
77\r
78static int\r
79op_sequenceIncludes(PyObject *seq, PyObject* ob)\r
80{\r
81 if (PyErr_WarnPy3k("operator.sequenceIncludes() is not supported "\r
82 "in 3.x. Use operator.contains().", 1) < 0)\r
83 return -1;\r
84 return PySequence_Contains(seq, ob);\r
85}\r
86\r
87spami(isCallable , op_isCallable)\r
88spami(isNumberType , PyNumber_Check)\r
89spami(truth , PyObject_IsTrue)\r
90spam2(op_add , PyNumber_Add)\r
91spam2(op_sub , PyNumber_Subtract)\r
92spam2(op_mul , PyNumber_Multiply)\r
93spam2(op_div , PyNumber_Divide)\r
94spam2(op_floordiv , PyNumber_FloorDivide)\r
95spam2(op_truediv , PyNumber_TrueDivide)\r
96spam2(op_mod , PyNumber_Remainder)\r
97spam1(op_neg , PyNumber_Negative)\r
98spam1(op_pos , PyNumber_Positive)\r
99spam1(op_abs , PyNumber_Absolute)\r
100spam1(op_inv , PyNumber_Invert)\r
101spam1(op_invert , PyNumber_Invert)\r
102spam2(op_lshift , PyNumber_Lshift)\r
103spam2(op_rshift , PyNumber_Rshift)\r
104spami(op_not_ , PyObject_Not)\r
105spam2(op_and_ , PyNumber_And)\r
106spam2(op_xor , PyNumber_Xor)\r
107spam2(op_or_ , PyNumber_Or)\r
108spam2(op_iadd , PyNumber_InPlaceAdd)\r
109spam2(op_isub , PyNumber_InPlaceSubtract)\r
110spam2(op_imul , PyNumber_InPlaceMultiply)\r
111spam2(op_idiv , PyNumber_InPlaceDivide)\r
112spam2(op_ifloordiv , PyNumber_InPlaceFloorDivide)\r
113spam2(op_itruediv , PyNumber_InPlaceTrueDivide)\r
114spam2(op_imod , PyNumber_InPlaceRemainder)\r
115spam2(op_ilshift , PyNumber_InPlaceLshift)\r
116spam2(op_irshift , PyNumber_InPlaceRshift)\r
117spam2(op_iand , PyNumber_InPlaceAnd)\r
118spam2(op_ixor , PyNumber_InPlaceXor)\r
119spam2(op_ior , PyNumber_InPlaceOr)\r
120spami(isSequenceType , PySequence_Check)\r
121spam2(op_concat , PySequence_Concat)\r
122spamoi(op_repeat , PySequence_Repeat)\r
123spam2(op_iconcat , PySequence_InPlaceConcat)\r
124spamoi(op_irepeat , PySequence_InPlaceRepeat)\r
125spami2b(op_contains , PySequence_Contains)\r
126spami2b(sequenceIncludes, op_sequenceIncludes)\r
127spamn2(indexOf , PySequence_Index)\r
128spamn2(countOf , PySequence_Count)\r
129spami(isMappingType , PyMapping_Check)\r
130spam2(op_getitem , PyObject_GetItem)\r
131spam2n(op_delitem , PyObject_DelItem)\r
132spam3n(op_setitem , PyObject_SetItem)\r
133spamrc(op_lt , Py_LT)\r
134spamrc(op_le , Py_LE)\r
135spamrc(op_eq , Py_EQ)\r
136spamrc(op_ne , Py_NE)\r
137spamrc(op_gt , Py_GT)\r
138spamrc(op_ge , Py_GE)\r
139\r
140static PyObject*\r
141op_pow(PyObject *s, PyObject *a)\r
142{\r
143 PyObject *a1, *a2;\r
144 if (PyArg_UnpackTuple(a,"pow", 2, 2, &a1, &a2))\r
145 return PyNumber_Power(a1, a2, Py_None);\r
146 return NULL;\r
147}\r
148\r
149static PyObject*\r
150op_ipow(PyObject *s, PyObject *a)\r
151{\r
152 PyObject *a1, *a2;\r
153 if (PyArg_UnpackTuple(a,"ipow", 2, 2, &a1, &a2))\r
154 return PyNumber_InPlacePower(a1, a2, Py_None);\r
155 return NULL;\r
156}\r
157\r
158static PyObject *\r
159op_index(PyObject *s, PyObject *a)\r
160{\r
161 return PyNumber_Index(a);\r
162}\r
163\r
164static PyObject*\r
165is_(PyObject *s, PyObject *a)\r
166{\r
167 PyObject *a1, *a2, *result = NULL;\r
168 if (PyArg_UnpackTuple(a,"is_", 2, 2, &a1, &a2)) {\r
169 result = (a1 == a2) ? Py_True : Py_False;\r
170 Py_INCREF(result);\r
171 }\r
172 return result;\r
173}\r
174\r
175static PyObject*\r
176is_not(PyObject *s, PyObject *a)\r
177{\r
178 PyObject *a1, *a2, *result = NULL;\r
179 if (PyArg_UnpackTuple(a,"is_not", 2, 2, &a1, &a2)) {\r
180 result = (a1 != a2) ? Py_True : Py_False;\r
181 Py_INCREF(result);\r
182 }\r
183 return result;\r
184}\r
185\r
186static PyObject*\r
187op_getslice(PyObject *s, PyObject *a)\r
188{\r
189 PyObject *a1;\r
190 Py_ssize_t a2, a3;\r
191\r
192 if (!PyArg_ParseTuple(a, "Onn:getslice", &a1, &a2, &a3))\r
193 return NULL;\r
194 return PySequence_GetSlice(a1, a2, a3);\r
195}\r
196\r
197static PyObject*\r
198op_setslice(PyObject *s, PyObject *a)\r
199{\r
200 PyObject *a1, *a4;\r
201 Py_ssize_t a2, a3;\r
202\r
203 if (!PyArg_ParseTuple(a, "OnnO:setslice", &a1, &a2, &a3, &a4))\r
204 return NULL;\r
205\r
206 if (-1 == PySequence_SetSlice(a1, a2, a3, a4))\r
207 return NULL;\r
208\r
209 Py_RETURN_NONE;\r
210}\r
211\r
212static PyObject*\r
213op_delslice(PyObject *s, PyObject *a)\r
214{\r
215 PyObject *a1;\r
216 Py_ssize_t a2, a3;\r
217\r
218 if (!PyArg_ParseTuple(a, "Onn:delslice", &a1, &a2, &a3))\r
219 return NULL;\r
220\r
221 if (-1 == PySequence_DelSlice(a1, a2, a3))\r
222 return NULL;\r
223\r
224 Py_RETURN_NONE;\r
225}\r
226\r
227#undef spam1\r
228#undef spam2\r
229#undef spam1o\r
230#undef spam1o\r
231#define spam1(OP,DOC) {#OP, OP, METH_VARARGS, PyDoc_STR(DOC)},\r
232#define spam2(OP,ALTOP,DOC) {#OP, op_##OP, METH_VARARGS, PyDoc_STR(DOC)}, \\r
233 {#ALTOP, op_##OP, METH_VARARGS, PyDoc_STR(DOC)},\r
234#define spam1o(OP,DOC) {#OP, OP, METH_O, PyDoc_STR(DOC)},\r
235#define spam2o(OP,ALTOP,DOC) {#OP, op_##OP, METH_O, PyDoc_STR(DOC)}, \\r
236 {#ALTOP, op_##OP, METH_O, PyDoc_STR(DOC)},\r
237\r
238\r
239\r
240/* compare_digest **********************************************************/\r
241\r
242/*\r
243 * timing safe compare\r
244 *\r
245 * Returns 1 of the strings are equal.\r
246 * In case of len(a) != len(b) the function tries to keep the timing\r
247 * dependent on the length of b. CPU cache locally may still alter timing\r
248 * a bit.\r
249 */\r
250static int\r
251_tscmp(const unsigned char *a, const unsigned char *b,\r
252 Py_ssize_t len_a, Py_ssize_t len_b)\r
253{\r
254 /* The volatile type declarations make sure that the compiler has no\r
255 * chance to optimize and fold the code in any way that may change\r
256 * the timing.\r
257 */\r
258 volatile Py_ssize_t length;\r
259 volatile const unsigned char *left;\r
260 volatile const unsigned char *right;\r
261 Py_ssize_t i;\r
262 unsigned char result;\r
263\r
264 /* loop count depends on length of b */\r
265 length = len_b;\r
266 left = NULL;\r
267 right = b;\r
268\r
269 /* don't use else here to keep the amount of CPU instructions constant,\r
270 * volatile forces re-evaluation\r
271 * */\r
272 if (len_a == length) {\r
273 left = *((volatile const unsigned char**)&a);\r
274 result = 0;\r
275 }\r
276 if (len_a != length) {\r
277 left = b;\r
278 result = 1;\r
279 }\r
280\r
281 for (i=0; i < length; i++) {\r
282 result |= *left++ ^ *right++;\r
283 }\r
284\r
285 return (result == 0);\r
286}\r
287\r
288PyDoc_STRVAR(compare_digest__doc__,\r
289"compare_digest(a, b) -> bool\n"\r
290"\n"\r
291"Return 'a == b'. This function uses an approach designed to prevent\n"\r
292"timing analysis, making it appropriate for cryptography.\n"\r
293"a and b must both be of the same type: either str (ASCII only),\n"\r
294"or any type that supports the buffer protocol (e.g. bytes).\n"\r
295"\n"\r
296"Note: If a and b are of different lengths, or if an error occurs,\n"\r
297"a timing attack could theoretically reveal information about the\n"\r
298"types and lengths of a and b--but not their values.\n");\r
299\r
300static PyObject*\r
301compare_digest(PyObject *self, PyObject *args)\r
302{\r
303 PyObject *a, *b;\r
304 int rc;\r
305\r
306 if (!PyArg_ParseTuple(args, "OO:compare_digest", &a, &b)) {\r
307 return NULL;\r
308 }\r
309\r
310 /* Unicode string */\r
311 if (PyUnicode_Check(a) && PyUnicode_Check(b)) {\r
312 rc = _tscmp((const unsigned char *)PyUnicode_AS_DATA(a),\r
313 (const unsigned char *)PyUnicode_AS_DATA(b),\r
314 PyUnicode_GET_DATA_SIZE(a),\r
315 PyUnicode_GET_DATA_SIZE(b));\r
316 }\r
317 /* fallback to buffer interface for bytes, bytesarray and other */\r
318 else {\r
319 Py_buffer view_a;\r
320 Py_buffer view_b;\r
321\r
322 if (PyObject_CheckBuffer(a) == 0 && PyObject_CheckBuffer(b) == 0) {\r
323 PyErr_Format(PyExc_TypeError,\r
324 "unsupported operand types(s) or combination of types: "\r
325 "'%.100s' and '%.100s'",\r
326 Py_TYPE(a)->tp_name, Py_TYPE(b)->tp_name);\r
327 return NULL;\r
328 }\r
329\r
330 if (PyObject_GetBuffer(a, &view_a, PyBUF_SIMPLE) == -1) {\r
331 return NULL;\r
332 }\r
333 if (view_a.ndim > 1) {\r
334 PyErr_SetString(PyExc_BufferError,\r
335 "Buffer must be single dimension");\r
336 PyBuffer_Release(&view_a);\r
337 return NULL;\r
338 }\r
339\r
340 if (PyObject_GetBuffer(b, &view_b, PyBUF_SIMPLE) == -1) {\r
341 PyBuffer_Release(&view_a);\r
342 return NULL;\r
343 }\r
344 if (view_b.ndim > 1) {\r
345 PyErr_SetString(PyExc_BufferError,\r
346 "Buffer must be single dimension");\r
347 PyBuffer_Release(&view_a);\r
348 PyBuffer_Release(&view_b);\r
349 return NULL;\r
350 }\r
351\r
352 rc = _tscmp((const unsigned char*)view_a.buf,\r
353 (const unsigned char*)view_b.buf,\r
354 view_a.len,\r
355 view_b.len);\r
356\r
357 PyBuffer_Release(&view_a);\r
358 PyBuffer_Release(&view_b);\r
359 }\r
360\r
361 return PyBool_FromLong(rc);\r
362}\r
363\r
364static struct PyMethodDef operator_methods[] = {\r
365\r
366spam1o(isCallable,\r
367 "isCallable(a) -- Same as callable(a).")\r
368spam1o(isNumberType,\r
369 "isNumberType(a) -- Return True if a has a numeric type, False otherwise.")\r
370spam1o(isSequenceType,\r
371 "isSequenceType(a) -- Return True if a has a sequence type, False otherwise.")\r
372spam1o(truth,\r
373 "truth(a) -- Return True if a is true, False otherwise.")\r
374spam2(contains,__contains__,\r
375 "contains(a, b) -- Same as b in a (note reversed operands).")\r
376spam1(sequenceIncludes,\r
377 "sequenceIncludes(a, b) -- Same as b in a (note reversed operands; deprecated).")\r
378spam1(indexOf,\r
379 "indexOf(a, b) -- Return the first index of b in a.")\r
380spam1(countOf,\r
381 "countOf(a, b) -- Return the number of times b occurs in a.")\r
382spam1o(isMappingType,\r
383 "isMappingType(a) -- Return True if a has a mapping type, False otherwise.")\r
384\r
385spam1(is_, "is_(a, b) -- Same as a is b.")\r
386spam1(is_not, "is_not(a, b) -- Same as a is not b.")\r
387spam2o(index, __index__, "index(a) -- Same as a.__index__()")\r
388spam2(add,__add__, "add(a, b) -- Same as a + b.")\r
389spam2(sub,__sub__, "sub(a, b) -- Same as a - b.")\r
390spam2(mul,__mul__, "mul(a, b) -- Same as a * b.")\r
391spam2(div,__div__, "div(a, b) -- Same as a / b when __future__.division is not in effect.")\r
392spam2(floordiv,__floordiv__, "floordiv(a, b) -- Same as a // b.")\r
393spam2(truediv,__truediv__, "truediv(a, b) -- Same as a / b when __future__.division is in effect.")\r
394spam2(mod,__mod__, "mod(a, b) -- Same as a % b.")\r
395spam2o(neg,__neg__, "neg(a) -- Same as -a.")\r
396spam2o(pos,__pos__, "pos(a) -- Same as +a.")\r
397spam2o(abs,__abs__, "abs(a) -- Same as abs(a).")\r
398spam2o(inv,__inv__, "inv(a) -- Same as ~a.")\r
399spam2o(invert,__invert__, "invert(a) -- Same as ~a.")\r
400spam2(lshift,__lshift__, "lshift(a, b) -- Same as a << b.")\r
401spam2(rshift,__rshift__, "rshift(a, b) -- Same as a >> b.")\r
402spam2o(not_,__not__, "not_(a) -- Same as not a.")\r
403spam2(and_,__and__, "and_(a, b) -- Same as a & b.")\r
404spam2(xor,__xor__, "xor(a, b) -- Same as a ^ b.")\r
405spam2(or_,__or__, "or_(a, b) -- Same as a | b.")\r
406spam2(iadd,__iadd__, "a = iadd(a, b) -- Same as a += b.")\r
407spam2(isub,__isub__, "a = isub(a, b) -- Same as a -= b.")\r
408spam2(imul,__imul__, "a = imul(a, b) -- Same as a *= b.")\r
409spam2(idiv,__idiv__, "a = idiv(a, b) -- Same as a /= b when __future__.division is not in effect.")\r
410spam2(ifloordiv,__ifloordiv__, "a = ifloordiv(a, b) -- Same as a //= b.")\r
411spam2(itruediv,__itruediv__, "a = itruediv(a, b) -- Same as a /= b when __future__.division is in effect.")\r
412spam2(imod,__imod__, "a = imod(a, b) -- Same as a %= b.")\r
413spam2(ilshift,__ilshift__, "a = ilshift(a, b) -- Same as a <<= b.")\r
414spam2(irshift,__irshift__, "a = irshift(a, b) -- Same as a >>= b.")\r
415spam2(iand,__iand__, "a = iand(a, b) -- Same as a &= b.")\r
416spam2(ixor,__ixor__, "a = ixor(a, b) -- Same as a ^= b.")\r
417spam2(ior,__ior__, "a = ior(a, b) -- Same as a |= b.")\r
418spam2(concat,__concat__,\r
419 "concat(a, b) -- Same as a + b, for a and b sequences.")\r
420spam2(repeat,__repeat__,\r
421 "repeat(a, b) -- Return a * b, where a is a sequence, and b is an integer.")\r
422spam2(iconcat,__iconcat__,\r
423 "a = iconcat(a, b) -- Same as a += b, for a and b sequences.")\r
424spam2(irepeat,__irepeat__,\r
425 "a = irepeat(a, b) -- Same as a *= b, where a is a sequence, and b is an integer.")\r
426spam2(getitem,__getitem__,\r
427 "getitem(a, b) -- Same as a[b].")\r
428spam2(setitem,__setitem__,\r
429 "setitem(a, b, c) -- Same as a[b] = c.")\r
430spam2(delitem,__delitem__,\r
431 "delitem(a, b) -- Same as del a[b].")\r
432spam2(pow,__pow__, "pow(a, b) -- Same as a ** b.")\r
433spam2(ipow,__ipow__, "a = ipow(a, b) -- Same as a **= b.")\r
434spam2(getslice,__getslice__,\r
435 "getslice(a, b, c) -- Same as a[b:c].")\r
436spam2(setslice,__setslice__,\r
437"setslice(a, b, c, d) -- Same as a[b:c] = d.")\r
438spam2(delslice,__delslice__,\r
439"delslice(a, b, c) -- Same as del a[b:c].")\r
440spam2(lt,__lt__, "lt(a, b) -- Same as a<b.")\r
441spam2(le,__le__, "le(a, b) -- Same as a<=b.")\r
442spam2(eq,__eq__, "eq(a, b) -- Same as a==b.")\r
443spam2(ne,__ne__, "ne(a, b) -- Same as a!=b.")\r
444spam2(gt,__gt__, "gt(a, b) -- Same as a>b.")\r
445spam2(ge,__ge__, "ge(a, b) -- Same as a>=b.")\r
446\r
447 {"_compare_digest", (PyCFunction)compare_digest, METH_VARARGS,\r
448 compare_digest__doc__},\r
449 {NULL, NULL} /* sentinel */\r
450\r
451};\r
452\r
453/* itemgetter object **********************************************************/\r
454\r
455typedef struct {\r
456 PyObject_HEAD\r
457 Py_ssize_t nitems;\r
458 PyObject *item;\r
459} itemgetterobject;\r
460\r
461static PyTypeObject itemgetter_type;\r
462\r
463static PyObject *\r
464itemgetter_new(PyTypeObject *type, PyObject *args, PyObject *kwds)\r
465{\r
466 itemgetterobject *ig;\r
467 PyObject *item;\r
468 Py_ssize_t nitems;\r
469\r
470 if (!_PyArg_NoKeywords("itemgetter()", kwds))\r
471 return NULL;\r
472\r
473 nitems = PyTuple_GET_SIZE(args);\r
474 if (nitems <= 1) {\r
475 if (!PyArg_UnpackTuple(args, "itemgetter", 1, 1, &item))\r
476 return NULL;\r
477 } else\r
478 item = args;\r
479\r
480 /* create itemgetterobject structure */\r
481 ig = PyObject_GC_New(itemgetterobject, &itemgetter_type);\r
482 if (ig == NULL)\r
483 return NULL;\r
484\r
485 Py_INCREF(item);\r
486 ig->item = item;\r
487 ig->nitems = nitems;\r
488\r
489 PyObject_GC_Track(ig);\r
490 return (PyObject *)ig;\r
491}\r
492\r
493static void\r
494itemgetter_dealloc(itemgetterobject *ig)\r
495{\r
496 PyObject_GC_UnTrack(ig);\r
497 Py_XDECREF(ig->item);\r
498 PyObject_GC_Del(ig);\r
499}\r
500\r
501static int\r
502itemgetter_traverse(itemgetterobject *ig, visitproc visit, void *arg)\r
503{\r
504 Py_VISIT(ig->item);\r
505 return 0;\r
506}\r
507\r
508static PyObject *\r
509itemgetter_call(itemgetterobject *ig, PyObject *args, PyObject *kw)\r
510{\r
511 PyObject *obj, *result;\r
512 Py_ssize_t i, nitems=ig->nitems;\r
513\r
514 if (!PyArg_UnpackTuple(args, "itemgetter", 1, 1, &obj))\r
515 return NULL;\r
516 if (nitems == 1)\r
517 return PyObject_GetItem(obj, ig->item);\r
518\r
519 assert(PyTuple_Check(ig->item));\r
520 assert(PyTuple_GET_SIZE(ig->item) == nitems);\r
521\r
522 result = PyTuple_New(nitems);\r
523 if (result == NULL)\r
524 return NULL;\r
525\r
526 for (i=0 ; i < nitems ; i++) {\r
527 PyObject *item, *val;\r
528 item = PyTuple_GET_ITEM(ig->item, i);\r
529 val = PyObject_GetItem(obj, item);\r
530 if (val == NULL) {\r
531 Py_DECREF(result);\r
532 return NULL;\r
533 }\r
534 PyTuple_SET_ITEM(result, i, val);\r
535 }\r
536 return result;\r
537}\r
538\r
539PyDoc_STRVAR(itemgetter_doc,\r
540"itemgetter(item, ...) --> itemgetter object\n\\r
541\n\\r
542Return a callable object that fetches the given item(s) from its operand.\n\\r
543After f = itemgetter(2), the call f(r) returns r[2].\n\\r
544After g = itemgetter(2, 5, 3), the call g(r) returns (r[2], r[5], r[3])");\r
545\r
546static PyTypeObject itemgetter_type = {\r
547 PyVarObject_HEAD_INIT(NULL, 0)\r
548 "operator.itemgetter", /* tp_name */\r
549 sizeof(itemgetterobject), /* tp_basicsize */\r
550 0, /* tp_itemsize */\r
551 /* methods */\r
552 (destructor)itemgetter_dealloc, /* tp_dealloc */\r
553 0, /* tp_print */\r
554 0, /* tp_getattr */\r
555 0, /* tp_setattr */\r
556 0, /* tp_compare */\r
557 0, /* tp_repr */\r
558 0, /* tp_as_number */\r
559 0, /* tp_as_sequence */\r
560 0, /* tp_as_mapping */\r
561 0, /* tp_hash */\r
562 (ternaryfunc)itemgetter_call, /* tp_call */\r
563 0, /* tp_str */\r
564 PyObject_GenericGetAttr, /* tp_getattro */\r
565 0, /* tp_setattro */\r
566 0, /* tp_as_buffer */\r
567 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */\r
568 itemgetter_doc, /* tp_doc */\r
569 (traverseproc)itemgetter_traverse, /* tp_traverse */\r
570 0, /* tp_clear */\r
571 0, /* tp_richcompare */\r
572 0, /* tp_weaklistoffset */\r
573 0, /* tp_iter */\r
574 0, /* tp_iternext */\r
575 0, /* tp_methods */\r
576 0, /* tp_members */\r
577 0, /* tp_getset */\r
578 0, /* tp_base */\r
579 0, /* tp_dict */\r
580 0, /* tp_descr_get */\r
581 0, /* tp_descr_set */\r
582 0, /* tp_dictoffset */\r
583 0, /* tp_init */\r
584 0, /* tp_alloc */\r
585 itemgetter_new, /* tp_new */\r
586 0, /* tp_free */\r
587};\r
588\r
589\r
590/* attrgetter object **********************************************************/\r
591\r
592typedef struct {\r
593 PyObject_HEAD\r
594 Py_ssize_t nattrs;\r
595 PyObject *attr;\r
596} attrgetterobject;\r
597\r
598static PyTypeObject attrgetter_type;\r
599\r
600static PyObject *\r
601attrgetter_new(PyTypeObject *type, PyObject *args, PyObject *kwds)\r
602{\r
603 attrgetterobject *ag;\r
604 PyObject *attr;\r
605 Py_ssize_t nattrs;\r
606\r
607 if (!_PyArg_NoKeywords("attrgetter()", kwds))\r
608 return NULL;\r
609\r
610 nattrs = PyTuple_GET_SIZE(args);\r
611 if (nattrs <= 1) {\r
612 if (!PyArg_UnpackTuple(args, "attrgetter", 1, 1, &attr))\r
613 return NULL;\r
614 } else\r
615 attr = args;\r
616\r
617 /* create attrgetterobject structure */\r
618 ag = PyObject_GC_New(attrgetterobject, &attrgetter_type);\r
619 if (ag == NULL)\r
620 return NULL;\r
621\r
622 Py_INCREF(attr);\r
623 ag->attr = attr;\r
624 ag->nattrs = nattrs;\r
625\r
626 PyObject_GC_Track(ag);\r
627 return (PyObject *)ag;\r
628}\r
629\r
630static void\r
631attrgetter_dealloc(attrgetterobject *ag)\r
632{\r
633 PyObject_GC_UnTrack(ag);\r
634 Py_XDECREF(ag->attr);\r
635 PyObject_GC_Del(ag);\r
636}\r
637\r
638static int\r
639attrgetter_traverse(attrgetterobject *ag, visitproc visit, void *arg)\r
640{\r
641 Py_VISIT(ag->attr);\r
642 return 0;\r
643}\r
644\r
645static PyObject *\r
646dotted_getattr(PyObject *obj, PyObject *attr)\r
647{\r
648 char *s, *p;\r
649\r
650#ifdef Py_USING_UNICODE\r
651 if (PyUnicode_Check(attr)) {\r
652 attr = _PyUnicode_AsDefaultEncodedString(attr, NULL);\r
653 if (attr == NULL)\r
654 return NULL;\r
655 }\r
656#endif\r
657\r
658 if (!PyString_Check(attr)) {\r
659 PyErr_SetString(PyExc_TypeError,\r
660 "attribute name must be a string");\r
661 return NULL;\r
662 }\r
663\r
664 s = PyString_AS_STRING(attr);\r
665 Py_INCREF(obj);\r
666 for (;;) {\r
667 PyObject *newobj, *str;\r
668 p = strchr(s, '.');\r
669 str = p ? PyString_FromStringAndSize(s, (p-s)) :\r
670 PyString_FromString(s);\r
671 if (str == NULL) {\r
672 Py_DECREF(obj);\r
673 return NULL;\r
674 }\r
675 newobj = PyObject_GetAttr(obj, str);\r
676 Py_DECREF(str);\r
677 Py_DECREF(obj);\r
678 if (newobj == NULL)\r
679 return NULL;\r
680 obj = newobj;\r
681 if (p == NULL) break;\r
682 s = p+1;\r
683 }\r
684\r
685 return obj;\r
686}\r
687\r
688static PyObject *\r
689attrgetter_call(attrgetterobject *ag, PyObject *args, PyObject *kw)\r
690{\r
691 PyObject *obj, *result;\r
692 Py_ssize_t i, nattrs=ag->nattrs;\r
693\r
694 if (!PyArg_UnpackTuple(args, "attrgetter", 1, 1, &obj))\r
695 return NULL;\r
696 if (ag->nattrs == 1)\r
697 return dotted_getattr(obj, ag->attr);\r
698\r
699 assert(PyTuple_Check(ag->attr));\r
700 assert(PyTuple_GET_SIZE(ag->attr) == nattrs);\r
701\r
702 result = PyTuple_New(nattrs);\r
703 if (result == NULL)\r
704 return NULL;\r
705\r
706 for (i=0 ; i < nattrs ; i++) {\r
707 PyObject *attr, *val;\r
708 attr = PyTuple_GET_ITEM(ag->attr, i);\r
709 val = dotted_getattr(obj, attr);\r
710 if (val == NULL) {\r
711 Py_DECREF(result);\r
712 return NULL;\r
713 }\r
714 PyTuple_SET_ITEM(result, i, val);\r
715 }\r
716 return result;\r
717}\r
718\r
719PyDoc_STRVAR(attrgetter_doc,\r
720"attrgetter(attr, ...) --> attrgetter object\n\\r
721\n\\r
722Return a callable object that fetches the given attribute(s) from its operand.\n\\r
723After f = attrgetter('name'), the call f(r) returns r.name.\n\\r
724After g = attrgetter('name', 'date'), the call g(r) returns (r.name, r.date).\n\\r
725After h = attrgetter('name.first', 'name.last'), the call h(r) returns\n\\r
726(r.name.first, r.name.last).");\r
727\r
728static PyTypeObject attrgetter_type = {\r
729 PyVarObject_HEAD_INIT(NULL, 0)\r
730 "operator.attrgetter", /* tp_name */\r
731 sizeof(attrgetterobject), /* tp_basicsize */\r
732 0, /* tp_itemsize */\r
733 /* methods */\r
734 (destructor)attrgetter_dealloc, /* tp_dealloc */\r
735 0, /* tp_print */\r
736 0, /* tp_getattr */\r
737 0, /* tp_setattr */\r
738 0, /* tp_compare */\r
739 0, /* tp_repr */\r
740 0, /* tp_as_number */\r
741 0, /* tp_as_sequence */\r
742 0, /* tp_as_mapping */\r
743 0, /* tp_hash */\r
744 (ternaryfunc)attrgetter_call, /* tp_call */\r
745 0, /* tp_str */\r
746 PyObject_GenericGetAttr, /* tp_getattro */\r
747 0, /* tp_setattro */\r
748 0, /* tp_as_buffer */\r
749 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */\r
750 attrgetter_doc, /* tp_doc */\r
751 (traverseproc)attrgetter_traverse, /* tp_traverse */\r
752 0, /* tp_clear */\r
753 0, /* tp_richcompare */\r
754 0, /* tp_weaklistoffset */\r
755 0, /* tp_iter */\r
756 0, /* tp_iternext */\r
757 0, /* tp_methods */\r
758 0, /* tp_members */\r
759 0, /* tp_getset */\r
760 0, /* tp_base */\r
761 0, /* tp_dict */\r
762 0, /* tp_descr_get */\r
763 0, /* tp_descr_set */\r
764 0, /* tp_dictoffset */\r
765 0, /* tp_init */\r
766 0, /* tp_alloc */\r
767 attrgetter_new, /* tp_new */\r
768 0, /* tp_free */\r
769};\r
770\r
771\r
772/* methodcaller object **********************************************************/\r
773\r
774typedef struct {\r
775 PyObject_HEAD\r
776 PyObject *name;\r
777 PyObject *args;\r
778 PyObject *kwds;\r
779} methodcallerobject;\r
780\r
781static PyTypeObject methodcaller_type;\r
782\r
783static PyObject *\r
784methodcaller_new(PyTypeObject *type, PyObject *args, PyObject *kwds)\r
785{\r
786 methodcallerobject *mc;\r
787 PyObject *name, *newargs;\r
788\r
789 if (PyTuple_GET_SIZE(args) < 1) {\r
790 PyErr_SetString(PyExc_TypeError, "methodcaller needs at least "\r
791 "one argument, the method name");\r
792 return NULL;\r
793 }\r
794\r
795 /* create methodcallerobject structure */\r
796 mc = PyObject_GC_New(methodcallerobject, &methodcaller_type);\r
797 if (mc == NULL)\r
798 return NULL;\r
799\r
800 newargs = PyTuple_GetSlice(args, 1, PyTuple_GET_SIZE(args));\r
801 if (newargs == NULL) {\r
802 Py_DECREF(mc);\r
803 return NULL;\r
804 }\r
805 mc->args = newargs;\r
806\r
807 name = PyTuple_GET_ITEM(args, 0);\r
808 Py_INCREF(name);\r
809 mc->name = name;\r
810\r
811 Py_XINCREF(kwds);\r
812 mc->kwds = kwds;\r
813\r
814 PyObject_GC_Track(mc);\r
815 return (PyObject *)mc;\r
816}\r
817\r
818static void\r
819methodcaller_dealloc(methodcallerobject *mc)\r
820{\r
821 PyObject_GC_UnTrack(mc);\r
822 Py_XDECREF(mc->name);\r
823 Py_XDECREF(mc->args);\r
824 Py_XDECREF(mc->kwds);\r
825 PyObject_GC_Del(mc);\r
826}\r
827\r
828static int\r
829methodcaller_traverse(methodcallerobject *mc, visitproc visit, void *arg)\r
830{\r
831 Py_VISIT(mc->args);\r
832 Py_VISIT(mc->kwds);\r
833 return 0;\r
834}\r
835\r
836static PyObject *\r
837methodcaller_call(methodcallerobject *mc, PyObject *args, PyObject *kw)\r
838{\r
839 PyObject *method, *obj, *result;\r
840\r
841 if (!PyArg_UnpackTuple(args, "methodcaller", 1, 1, &obj))\r
842 return NULL;\r
843 method = PyObject_GetAttr(obj, mc->name);\r
844 if (method == NULL)\r
845 return NULL;\r
846 result = PyObject_Call(method, mc->args, mc->kwds);\r
847 Py_DECREF(method);\r
848 return result;\r
849}\r
850\r
851PyDoc_STRVAR(methodcaller_doc,\r
852"methodcaller(name, ...) --> methodcaller object\n\\r
853\n\\r
854Return a callable object that calls the given method on its operand.\n\\r
855After f = methodcaller('name'), the call f(r) returns r.name().\n\\r
856After g = methodcaller('name', 'date', foo=1), the call g(r) returns\n\\r
857r.name('date', foo=1).");\r
858\r
859static PyTypeObject methodcaller_type = {\r
860 PyVarObject_HEAD_INIT(NULL, 0)\r
861 "operator.methodcaller", /* tp_name */\r
862 sizeof(methodcallerobject), /* tp_basicsize */\r
863 0, /* tp_itemsize */\r
864 /* methods */\r
865 (destructor)methodcaller_dealloc, /* tp_dealloc */\r
866 0, /* tp_print */\r
867 0, /* tp_getattr */\r
868 0, /* tp_setattr */\r
869 0, /* tp_compare */\r
870 0, /* tp_repr */\r
871 0, /* tp_as_number */\r
872 0, /* tp_as_sequence */\r
873 0, /* tp_as_mapping */\r
874 0, /* tp_hash */\r
875 (ternaryfunc)methodcaller_call, /* tp_call */\r
876 0, /* tp_str */\r
877 PyObject_GenericGetAttr, /* tp_getattro */\r
878 0, /* tp_setattro */\r
879 0, /* tp_as_buffer */\r
880 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */\r
881 methodcaller_doc, /* tp_doc */\r
882 (traverseproc)methodcaller_traverse, /* tp_traverse */\r
883 0, /* tp_clear */\r
884 0, /* tp_richcompare */\r
885 0, /* tp_weaklistoffset */\r
886 0, /* tp_iter */\r
887 0, /* tp_iternext */\r
888 0, /* tp_methods */\r
889 0, /* tp_members */\r
890 0, /* tp_getset */\r
891 0, /* tp_base */\r
892 0, /* tp_dict */\r
893 0, /* tp_descr_get */\r
894 0, /* tp_descr_set */\r
895 0, /* tp_dictoffset */\r
896 0, /* tp_init */\r
897 0, /* tp_alloc */\r
898 methodcaller_new, /* tp_new */\r
899 0, /* tp_free */\r
900};\r
901\r
902\r
903/* Initialization function for the module (*must* be called initoperator) */\r
904\r
905PyMODINIT_FUNC\r
906initoperator(void)\r
907{\r
908 PyObject *m;\r
909\r
910 /* Create the module and add the functions */\r
911 m = Py_InitModule4("operator", operator_methods, operator_doc,\r
912 (PyObject*)NULL, PYTHON_API_VERSION);\r
913 if (m == NULL)\r
914 return;\r
915\r
916 if (PyType_Ready(&itemgetter_type) < 0)\r
917 return;\r
918 Py_INCREF(&itemgetter_type);\r
919 PyModule_AddObject(m, "itemgetter", (PyObject *)&itemgetter_type);\r
920\r
921 if (PyType_Ready(&attrgetter_type) < 0)\r
922 return;\r
923 Py_INCREF(&attrgetter_type);\r
924 PyModule_AddObject(m, "attrgetter", (PyObject *)&attrgetter_type);\r
925\r
926 if (PyType_Ready(&methodcaller_type) < 0)\r
927 return;\r
928 Py_INCREF(&methodcaller_type);\r
929 PyModule_AddObject(m, "methodcaller", (PyObject *)&methodcaller_type);\r
930}\r