root/releases/pkgcore/0.2.1/src/restrictions.c @ ferringb%2540gmail.com-20061208171721-2a9b9337a82cb9a7

Revision ferringb%2540gmail.com-20061208171721-2a9b9337a82cb9a7, 17.3 KB (checked in by Brian Harring <ferringb@…>, 2 years ago)

handle EBUSY, and only invoke the callback if the op succeeded for directories.

Line 
1/*
2 * Copyright: 2006 Brian Harring <ferringb@gmail.com>
3 * License: GPL2
4 *
5 * C version of some of pkgcore (for extra speed).
6 */
7
8/* This does not really do anything since we do not use the "#"
9 * specifier in a PyArg_Parse or similar call, but hey, not using it
10 * means we are Py_ssize_t-clean too!
11 */
12
13#define PY_SSIZE_T_CLEAN
14
15#include "common.h"
16#include <structmember.h>
17
18static PyObject *pkgcore_restrictions_type = NULL;
19static PyObject *pkgcore_restrictions_subtype = NULL;
20
21// global
22#define NEGATED_RESTRICT    0x1
23
24//strexactmatch
25#define CASE_SENSITIVE      0x2
26
27//packagerestriction
28#define IGNORE_MISSING      0x2
29#define SHALLOW_ATTR        0x4
30
31
32#define IS_NEGATED(flags) (flags & NEGATED_RESTRICT)
33
34typedef struct {
35    PyObject_HEAD
36    PyObject *exact;
37    PyObject *hash;
38    char flags;
39} pkgcore_StrExactMatch;
40
41static void
42pkgcore_StrExactMatch_dealloc(pkgcore_StrExactMatch *self)
43{
44    Py_CLEAR(self->hash);
45    Py_DECREF(self->exact);
46    self->ob_type->tp_free((PyObject *)self);
47}
48
49static PyObject *
50pkgcore_StrExactMatch_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
51{
52    PyObject *exact, *sensitive = NULL, *negate = NULL;
53
54    static char *kwlist[] = {"exact", "case_sensitive", "negate", NULL};
55    if(!PyArg_ParseTupleAndKeywords(args, kwds, "O|OO", kwlist,
56        &exact, &sensitive, &negate)) {
57        return NULL;
58    } else if(!PyString_Check(exact) && !PyUnicode_Check(exact)) {
59        PyObject *tmp = PyObject_Str(exact);
60        if(!tmp)
61            return NULL;
62        exact = tmp;
63    }
64    char flags = 0;
65    #define set_bool(ptr, statement)        \
66    if(ptr) {                               \
67        if(ptr == Py_True) {                \
68            statement;                      \
69        } else if (ptr != Py_False) {       \
70            if(PyObject_IsTrue(ptr)) {      \
71                statement;                  \
72            } else if (PyErr_Occurred()) {  \
73                return NULL;                \
74            }                               \
75        }                                   \
76    }
77    set_bool(sensitive, flags |= CASE_SENSITIVE)
78    else
79        flags |= CASE_SENSITIVE;
80    set_bool(negate, flags |= NEGATED_RESTRICT);
81    #undef set_bool
82   
83    // alloc now.
84    pkgcore_StrExactMatch *self = \
85        (pkgcore_StrExactMatch *)type->tp_alloc(type, 0);
86    if(!self)
87        return NULL;
88    self->flags = flags;
89    self->hash = NULL;
90    if(!(flags & CASE_SENSITIVE)) {
91        self->exact = PyObject_CallMethod(exact, "lower", NULL);
92        if(!exact)
93            Py_CLEAR(self);
94    } else {
95        Py_INCREF(exact);
96        self->exact = exact;
97    }
98    if(self) {
99        PyObject *tmp = PyTuple_New(3);
100        if(!tmp) {
101            Py_CLEAR(self);
102        }
103        PyTuple_SET_ITEM(tmp, 0, self->exact);
104        PyTuple_SET_ITEM(tmp, 1, IS_NEGATED(self->flags) ? Py_True : Py_False);
105        PyTuple_SET_ITEM(tmp, 2, (self->flags & CASE_SENSITIVE) ?
106            Py_True : Py_False);
107        long hash = PyObject_Hash(tmp);
108        PyTuple_SET_ITEM(tmp, 0, NULL);
109        PyTuple_SET_ITEM(tmp, 1, NULL);
110        PyTuple_SET_ITEM(tmp, 2, NULL);
111        Py_DECREF(tmp);
112        if(hash == -1 || !(self->hash = PyLong_FromLong(hash))) {
113            Py_DECREF(self);
114        }
115    }
116    return (PyObject *)self;
117}
118
119PyObject *
120pkgcore_StrExactMatch_richcompare(pkgcore_StrExactMatch *self,
121    pkgcore_StrExactMatch *other, int op)
122{
123    PyObject *result;
124    if(op != Py_EQ && op != Py_NE) {
125        result = Py_NotImplemented;
126    } else if(self == other) {
127        result = op == Py_EQ ? Py_True : Py_False;
128    } else if (self->flags != other->flags) {
129        result = op == Py_NE ? Py_True : Py_False;
130    } else {
131        return PyObject_RichCompare(self->exact, other->exact, op);
132    }
133    Py_INCREF(result);
134    return result;
135}
136
137static PyObject *
138pkgcore_StrExactMatch_match(pkgcore_StrExactMatch *self,
139    PyObject *value)
140{
141    PyObject *real_value = value;
142    if(!PyString_Check(value) && !PyUnicode_Check(value)) {
143        PyObject *tmp = PyObject_Str(value);
144        if(!tmp)
145            return tmp;
146        real_value = tmp;
147    } else
148        real_value = value;
149    if(!(self->flags & CASE_SENSITIVE)) {
150        PyObject *tmp = PyObject_CallMethod(value, "lower", NULL);
151
152        if(real_value != value) {
153            Py_DECREF(real_value);
154        }
155
156        if(!tmp)
157            return NULL;
158        real_value = tmp;
159    }
160    PyObject *ret = PyObject_RichCompare(self->exact, real_value,
161        IS_NEGATED(self->flags) ? Py_NE : Py_EQ);
162
163    if(real_value != value) {
164        Py_DECREF(real_value);
165    }
166
167    return ret;
168}
169
170static PyMethodDef pkgcore_StrExactMatch_methods[] = {
171    {"match", (PyCFunction)pkgcore_StrExactMatch_match, METH_O},
172    {NULL}
173};
174
175PyDoc_STRVAR(
176    pkgcore_StrExactMatch_documentation,
177    "\nexact string comparison match\n"
178    "@param exact: exact basestring to match\n"
179    "@keyword case_sensitive: should the match be case sensitive? "
180        "(default: True)\n"
181    "@keyword negate: should the match results be inverted? (default: False)\n"
182    );
183
184
185static PyMemberDef pkgcore_StrExactMatch_members[] = {
186    {"exact", T_OBJECT, offsetof(pkgcore_StrExactMatch, exact), READONLY},
187    {"_hash", T_OBJECT, offsetof(pkgcore_StrExactMatch, hash), READONLY},
188    {NULL}
189};
190
191PKGCORE_IMMUTABLE_ATTR_BOOL(pkgcore_StrExactMatch, "negate", negate,
192    (self->flags & NEGATED_RESTRICT))
193PKGCORE_IMMUTABLE_ATTR_BOOL(pkgcore_StrExactMatch, "case_sensitive", case,
194    (self->flags & CASE_SENSITIVE))
195
196static PyGetSetDef pkgcore_StrExactMatch_attrs[] = {
197PKGCORE_GETSET(pkgcore_StrExactMatch, "negate", negate),
198PKGCORE_GETSET(pkgcore_StrExactMatch, "case_sensitive", case),
199    {NULL}
200};
201
202static PyTypeObject pkgcore_StrExactMatch_Type = {
203    PyObject_HEAD_INIT(NULL)
204    0,                                               /* ob_size*/
205    "pkgcore.restrictions._restrictions.StrExactMatch",
206                                                     /* tp_name*/
207    sizeof(pkgcore_StrExactMatch),                   /* tp_basicsize*/
208    0,                                               /* tp_itemsize*/
209    (destructor)pkgcore_StrExactMatch_dealloc,       /* tp_dealloc*/
210    0,                                               /* tp_print*/
211    0,                                               /* tp_getattr*/
212    0,                                               /* tp_setattr*/
213    0,                                               /* tp_compare*/
214    0,                                               /* tp_repr*/
215    0,                                               /* tp_as_number*/
216    0,                                               /* tp_as_sequence*/
217    0,                                               /* tp_as_mapping*/
218    0,                                               /* tp_hash */
219    (ternaryfunc)0,                                  /* tp_call*/
220    (reprfunc)0,                                     /* tp_str*/
221    0,                                               /* tp_getattro*/
222    0,                                               /* tp_setattro*/
223    0,                                               /* tp_as_buffer*/
224    Py_TPFLAGS_BASETYPE|Py_TPFLAGS_DEFAULT,                              /* tp_flags*/
225    pkgcore_StrExactMatch_documentation,             /* tp_doc */
226    (traverseproc)0,                                 /* tp_traverse */
227    (inquiry)0,                                      /* tp_clear */
228    (richcmpfunc)pkgcore_StrExactMatch_richcompare,  /* tp_richcompare */
229    0,                                               /* tp_weaklistoffset */
230    (getiterfunc)0,                                  /* tp_iter */
231    (iternextfunc)0,                                 /* tp_iternext */
232    pkgcore_StrExactMatch_methods,                   /* tp_methods */
233    pkgcore_StrExactMatch_members,                   /* tp_members */
234    pkgcore_StrExactMatch_attrs,                     /* tp_getset */
235    0,                                               /* tp_base */
236    0,                                               /* tp_dict */
237    0,                                               /* tp_descr_get */
238    0,                                               /* tp_descr_set */
239    0,                                               /* tp_dictoffset */
240    (initproc)0,                                     /* tp_init */
241    0,                                               /* tp_alloc */
242    pkgcore_StrExactMatch_new,                       /* tp_new */
243};
244
245
246typedef struct {
247    PyObject_HEAD
248    PyObject *attr;
249    PyObject *restriction;
250    char flags;
251} pkgcore_PackageRestriction;
252
253static int
254pkgcore_PackageRestriction_traverse(pkgcore_PackageRestriction *self,
255    visitproc visit, void *arg)
256{
257    Py_VISIT(self->restriction);
258    return 0;
259}
260
261static PyObject *
262pkgcore_PackageRestriction_new(PyTypeObject *type,
263    PyObject *args, PyObject *kwds)
264{
265    PyObject *attr, *restriction, *negate = NULL, *ignore_missing = NULL;
266    static char *kwdlist[] = {"attr", "childrestriction", "negate",
267        "ignore_missing", NULL};
268    if(!PyArg_ParseTupleAndKeywords(args, kwds, "SO|OO", kwdlist,
269        &attr, &restriction, &negate, &ignore_missing)) {
270        return NULL;
271    }
272
273    char flags = 0;
274    #define make_bool(ptr, statement)                   \
275    if((ptr) != Py_True && (ptr) != Py_False) {         \
276        if((ptr) != Py_None) {                          \
277            int ret = PyObject_IsTrue(ptr);             \
278            if(ret == -1)                               \
279                return NULL;                            \
280            if(ret) { flags |= statement; }             \
281        }                                               \
282    } else if ((ptr) == Py_True) { flags |= statement;};
283    if(negate) {
284        make_bool(negate, NEGATED_RESTRICT);
285    }
286    if(!ignore_missing) {
287        flags |= IGNORE_MISSING;
288    } else {
289        make_bool(ignore_missing, IGNORE_MISSING);
290    }
291    #undef make_bool
292
293    pkgcore_PackageRestriction *self = \
294        (pkgcore_PackageRestriction *)type->tp_alloc(type, 0);
295    if(!self)
296        return NULL;
297    Py_INCREF(attr);
298    self->attr = attr;
299    Py_INCREF(restriction);
300    self->restriction = restriction;
301    if(NULL == index(PyString_AS_STRING(attr), '.'))
302        flags |= SHALLOW_ATTR;
303    self->flags = flags;
304    return (PyObject *)self;
305}
306
307PyObject *
308pkgcore_PackageRestriction_richcompare(pkgcore_PackageRestriction *self,
309    pkgcore_PackageRestriction *other, int op)
310{
311    if(op != Py_EQ && op != Py_NE) {
312        return Py_INCREF(Py_NotImplemented), Py_NotImplemented;
313    } else if(self == other) {
314        if(op == Py_EQ)
315            Py_RETURN_TRUE;
316        Py_RETURN_FALSE;
317    } else if (self->flags != other->flags) {
318        if(op == Py_EQ)
319            Py_RETURN_FALSE;
320        Py_RETURN_TRUE;
321    } else if(self->attr != other->attr) {
322        if(op == Py_EQ)
323            Py_RETURN_FALSE;
324        Py_RETURN_TRUE;
325    }
326    PyObject *ret = PyObject_RichCompare(self->attr, other->attr, op);
327    if (ret == Py_NotImplemented ||
328        ret == (op == Py_EQ ? Py_False : Py_True)) {
329        return ret;
330    }
331    Py_DECREF(ret);
332    return PyObject_RichCompare(self->restriction, other->restriction, op);
333}
334
335void
336pkgcore_PackageRestriction_dealloc(pkgcore_PackageRestriction *self)
337{
338    Py_CLEAR(self->attr);
339    Py_CLEAR(self->restriction);
340    self->ob_type->tp_free((PyObject *)self);
341}
342
343static PyObject *
344pkgcore_PackageRestriction_pull_attr(pkgcore_PackageRestriction *self,
345    PyObject *inst)
346{
347    if(self->flags & SHALLOW_ATTR) {
348        return PyObject_GetAttr(inst, self->attr);
349    }
350    char *pos = PyString_AS_STRING(self->attr);
351    char *start = pos;
352    PyObject *last = inst;
353    PyObject *new = NULL;
354    // note we're using the pystring comparison, instead of comparing inst
355    // against last; the reason is that a self referential lookup could
356    // return inst, and we'd leak a ref if we relied on that comparison
357    do {
358        while('.' != *pos && '\0' != *pos)
359            pos++;
360        PyObject *s = PyString_FromStringAndSize(start, pos - start);
361        if(!s) {
362            if(start != PyString_AS_STRING(self->attr)) {
363                Py_DECREF(last);
364            }
365            return NULL;
366        }
367        new = PyObject_GetAttr(last, s);
368        Py_DECREF(s);
369        if(start != PyString_AS_STRING(self->attr)) {
370            Py_DECREF(last);
371        }
372        if(!new)
373            return NULL;
374        last = new;
375        if('.' == *pos)
376            pos++;
377        start = pos;
378    } while ('\0' != *pos);
379    return new;
380}
381
382PyDoc_STRVAR(
383    pkgcore_PackageRestriction_documentation,
384    "cpython PackageRestriction base class for speed");
385
386static PyMemberDef pkgcore_PackageRestriction_members[] = {
387    {"restriction", T_OBJECT, offsetof(pkgcore_PackageRestriction, restriction),
388     READONLY},
389    {"attr", T_OBJECT, offsetof(pkgcore_PackageRestriction, attr), READONLY},
390    {NULL}
391};
392
393PKGCORE_IMMUTABLE_ATTR_BOOL(pkgcore_PackageRestriction, "negate", negate,
394    (self->flags & NEGATED_RESTRICT))
395PKGCORE_IMMUTABLE_ATTR_BOOL(pkgcore_PackageRestriction, "ignore_missing",
396    ignore_missing, (self->flags & IGNORE_MISSING))
397
398static PyGetSetDef pkgcore_PackageRestriction_attrs[] = {
399PKGCORE_GETSET(pkgcore_PackageRestriction, "negate", negate),
400PKGCORE_GETSET(pkgcore_PackageRestriction, "ignore_missing", ignore_missing),
401    {NULL}
402};
403
404static PyMethodDef pkgcore_PackageRestriction_methods[] = {
405    {"_pull_attr", (PyCFunction)pkgcore_PackageRestriction_pull_attr, METH_O},
406    {NULL}
407};
408
409static PyTypeObject pkgcore_PackageRestriction_Type = {
410    PyObject_HEAD_INIT(NULL)
411    0,                                              /* ob_size*/
412    "pkgcore.restrictions._restrictions.PackageRestriction",
413                                                    /* tp_name*/
414    sizeof(pkgcore_PackageRestriction),             /* tp_basicsize*/
415    0,                                              /* tp_itemsize*/
416    (destructor)pkgcore_PackageRestriction_dealloc, /* tp_dealloc*/
417    0,                                              /* tp_print*/
418    0,                                              /* tp_getattr*/
419    0,                                              /* tp_setattr*/
420    0,                                              /* tp_compare*/
421    0,                                              /* tp_repr*/
422    0,                                              /* tp_as_number*/
423    0,                                              /* tp_as_sequence*/
424    0,                                              /* tp_as_mapping*/
425    0,                                              /* tp_hash */
426    (ternaryfunc)0,                                 /* tp_call*/
427    (reprfunc)0,                                    /* tp_str*/
428    0,                                              /* tp_getattro*/
429    0,                                              /* tp_setattro*/
430    0,                                              /* tp_as_buffer*/
431    Py_TPFLAGS_BASETYPE|Py_TPFLAGS_DEFAULT,         /* tp_flags*/
432    pkgcore_PackageRestriction_documentation,       /* tp_doc */
433    (traverseproc)pkgcore_PackageRestriction_traverse,
434                                                    /* tp_traverse */
435    (inquiry)0,                                     /* tp_clear */
436    (richcmpfunc)pkgcore_PackageRestriction_richcompare,
437                                                    /* tp_richcompare */
438    0,                                              /* tp_weaklistoffset */
439    (getiterfunc)0,                                 /* tp_iter */
440    (iternextfunc)0,                                /* tp_iternext */
441    pkgcore_PackageRestriction_methods,             /* tp_methods */
442    pkgcore_PackageRestriction_members,             /* tp_members */
443    pkgcore_PackageRestriction_attrs,               /* tp_getset */
444    0,                                              /* tp_base */
445    0,                                              /* tp_dict */
446    0,                                              /* tp_descr_get */
447    0,                                              /* tp_descr_set */
448    0,                                              /* tp_dictoffset */
449    0,                                              /* tp_init */
450    0,                                              /* tp_alloc */
451    pkgcore_PackageRestriction_new,                 /* tp_new */
452};
453
454
455PyDoc_STRVAR(
456    pkgcore_restrictions_documentation,
457    "cpython restrictions extensions for speed");
458
459PyMODINIT_FUNC
460init_restrictions()
461{
462    PyObject *m = Py_InitModule3("_restrictions", NULL,
463        pkgcore_restrictions_documentation);
464    if (!m)
465        return;
466
467    if (PyType_Ready(&pkgcore_StrExactMatch_Type) < 0)
468        return;
469
470    if (PyType_Ready(&pkgcore_PackageRestriction_Type) < 0)
471        return;
472
473    #define LOAD_STR(ptr, val)                      \
474    if(!(ptr)) {                                    \
475        if(!((ptr) = PyString_FromString(val))) {   \
476            return;                                 \
477        }                                           \
478    }
479
480    LOAD_STR(pkgcore_restrictions_type, "type");
481    LOAD_STR(pkgcore_restrictions_subtype, "subtype");
482    #undef LOAD_STR
483
484    Py_INCREF(&pkgcore_StrExactMatch_Type);
485    if (PyModule_AddObject(
486            m, "StrExactMatch", (PyObject *)&pkgcore_StrExactMatch_Type) == -1)
487        return;
488
489    Py_INCREF(&pkgcore_PackageRestriction_Type);
490    if (PyModule_AddObject(
491            m, "PackageRestriction",
492            (PyObject *)&pkgcore_PackageRestriction_Type) == -1)
493        return;
494
495    /* Success! */
496}
Note: See TracBrowser for help on using the browser.