Skip to content

Commit a64a6cc

Browse files
marcantiwai
authored andcommitted
alsaseq: fix constant objects in Python 3
In Py3 everything is a long, so we can't get away with duplicating the integer object layout any more. Properly subclass PyLong_Type instead, with a bit of a hack to add an extra name field after the variable-sized data section. Also get rid of the enum type stuff, which seems to be unused cruft, and the numprotocol stuff, because the base type can take care of that (and we can't map arbitrary arithmetic results back to constants anyway). Signed-off-by: Hector Martin <[email protected]> Signed-off-by: Takashi Iwai <[email protected]>
1 parent e1bc1c2 commit a64a6cc

File tree

1 file changed

+52
-97
lines changed

1 file changed

+52
-97
lines changed

pyalsa/alsaseq.c

Lines changed: 52 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,6 @@
5151
/* the C variable of a constant dict */
5252
#define TDICT(subtype) _dictPYALSASEQ_CONST_##subtype
5353

54-
/* the C enumeration of a constant dict */
55-
#define TTYPE(subtype) PYALSASEQ_CONST_##subtype
56-
5754
/* defines constant dict by type */
5855
#define TCONSTDICT(subtype) \
5956
static PyObject * TDICT(subtype);
@@ -71,7 +68,7 @@
7168
/* creates a typed constant and add it to the module and dictionary */
7269
#define TCONSTADD(module, subtype, name) { \
7370
PyObject *tmp = \
74-
Constant_create(#name, SND_##name, TTYPE(subtype)); \
71+
Constant_create(#name, SND_##name); \
7572
if (tmp == NULL) { \
7673
return MOD_ERROR_VAL; \
7774
} \
@@ -109,46 +106,6 @@
109106
} \
110107
}
111108

112-
113-
/* num protocol support for binary Constant operations */
114-
#define NUMPROTOCOL2(name, oper) \
115-
static PyObject * \
116-
Constant_##name (PyObject *v, PyObject *w) { \
117-
int type = 0; \
118-
long val1, val2, val; \
119-
if (get_long1(v, &val1) || get_long1(w, &val2)) { \
120-
Py_INCREF(Py_NotImplemented); \
121-
return Py_NotImplemented; \
122-
} \
123-
val = val1 oper val2; \
124-
/* always asume left will be the type */ \
125-
if (PyObject_TypeCheck(v, &ConstantType)) { \
126-
type = ((ConstantObject *) v)->type; \
127-
} else if (PyObject_TypeCheck(w, &ConstantType)) { \
128-
type = ((ConstantObject *) w)->type; \
129-
} \
130-
PyObject *self = Constant_create(#oper, val, type); \
131-
return self; \
132-
}
133-
134-
/* num protocol support for unary Constant operations */
135-
#define NUMPROTOCOL1(name, oper) \
136-
static PyObject * \
137-
Constant_##name (PyObject *v) { \
138-
int type = 0; \
139-
long val1, val; \
140-
if (get_long1(v, &val1)) { \
141-
Py_INCREF(Py_NotImplemented); \
142-
return Py_NotImplemented; \
143-
} \
144-
val = oper val1; \
145-
if (PyObject_TypeCheck(v, &ConstantType)) { \
146-
type = ((ConstantObject *) v)->type; \
147-
} \
148-
PyObject *self = Constant_create(#oper, val, type); \
149-
return self; \
150-
}
151-
152109
/* sets the object into the dict */
153110
#define SETDICTOBJ(name, object) \
154111
PyDict_SetItemString(dict, name, object)
@@ -328,21 +285,6 @@
328285
// alsaseq.Constant implementation
329286
//////////////////////////////////////////////////////////////////////////////
330287

331-
/* alsaseq.Constant->type enumeration */
332-
enum {
333-
PYALSASEQ_CONST_STREAMS,
334-
PYALSASEQ_CONST_MODE,
335-
PYALSASEQ_CONST_QUEUE,
336-
PYALSASEQ_CONST_CLIENT_TYPE,
337-
PYALSASEQ_CONST_PORT_CAP,
338-
PYALSASEQ_CONST_PORT_TYPE,
339-
PYALSASEQ_CONST_EVENT_TYPE,
340-
PYALSASEQ_CONST_EVENT_TIMESTAMP,
341-
PYALSASEQ_CONST_EVENT_TIMEMODE,
342-
PYALSASEQ_CONST_ADDR_CLIENT,
343-
PYALSASEQ_CONST_ADDR_PORT,
344-
};
345-
346288
// constants dictionaries
347289

348290
TCONSTDICT(STREAMS);
@@ -390,34 +332,66 @@ PyDoc_STRVAR(Constant__doc__,
390332
"Python number protocol."
391333
);
392334

393-
/** alsaseq.Constant object structure type */
335+
/** alsaseq.Constant additional fields */
336+
/* This follows the variable length portion of the Long type */
394337
typedef struct {
395-
PyObject_HEAD
396-
;
397-
398-
/* value of constant */
399-
unsigned long int value;
400338
/* name of constant */
401339
const char *name;
402-
/* type of constant */
403-
int type;
340+
} ConstantExtraFields;
341+
342+
/** alsaseq.Constant object structure type */
343+
typedef struct {
344+
#if PY_MAJOR_VERSION < 3
345+
PyIntObject base;
346+
#else
347+
/* NOTE: this only works if the value fits in one digit */
348+
PyLongObject base;
349+
#endif
350+
/* This field is actually offset by the base type's variable size portion */
351+
ConstantExtraFields extra;
404352
} ConstantObject;
405353

354+
#if PY_MAJOR_VERSION < 3
355+
/* PyInt is fixed size in Python 2 */
356+
# define CONST_VALUE(x) PyInt_AsLong((PyObject *)x)
357+
# define CONST_EXTRA(x) (&(x->extra))
358+
#else
359+
/* PyLong is variable size in Python 3 */
360+
# define CONST_VALUE(x) PyLong_AsLong((PyObject *)x)
361+
# define CONST_EXTRA(x) \
362+
((ConstantExtraFields *)( \
363+
((intptr_t)(&x->extra)) \
364+
+ abs(Py_SIZE(&x->base)) * Py_TYPE(x)->tp_itemsize \
365+
))
366+
#endif
367+
406368
/** alsaseq.Constant type (initialized later...) */
407369
static PyTypeObject ConstantType;
408370

409371
/** alsaseq.Constant internal create */
410372
static PyObject *
411-
Constant_create(const char *name, long value, int type) {
412-
ConstantObject *self = PyObject_New(ConstantObject, &ConstantType);
373+
Constant_create(const char *name, long value) {
374+
#if PY_MAJOR_VERSION < 3
375+
PyObject *val = PyInt_FromLong(value);
376+
#else
377+
PyObject *val = PyLong_FromLong(value);
378+
#endif
379+
380+
PyObject *args = PyTuple_Pack(1, val);
381+
Py_DECREF(val);
382+
383+
#if PY_MAJOR_VERSION < 3
384+
ConstantObject *self = (ConstantObject *)PyInt_Type.tp_new(&ConstantType, args, NULL);
385+
#else
386+
ConstantObject *self = (ConstantObject *)PyLong_Type.tp_new(&ConstantType, args, NULL);
387+
#endif
388+
Py_DECREF(args);
413389

414390
if (self == NULL) {
415391
return NULL;
416392
}
417393

418-
self->value = value;
419-
self->name = name;
420-
self->type = type;
394+
CONST_EXTRA(self)->name = name;
421395

422396
return (PyObject *)self;
423397
}
@@ -426,34 +400,16 @@ Constant_create(const char *name, long value, int type) {
426400
static PyObject *
427401
Constant_repr(ConstantObject *self) {
428402
return PyUnicode_FromFormat("%s(0x%x)",
429-
self->name,
430-
(unsigned int)self->value);
403+
CONST_EXTRA(self)->name,
404+
(unsigned int)CONST_VALUE(self));
431405
}
432406

433407
/** alsaseq.Constant tp_str */
434408
static PyObject *
435409
Constant_str(ConstantObject *self) {
436410
return PyUnicode_FromFormat("%s",
437-
self->name);
438-
}
439-
440-
/** alsaseq.Constant Number protocol support (note: not all ops supported) */
441-
NUMPROTOCOL2(Add, +)
442-
NUMPROTOCOL2(Subtract, -)
443-
NUMPROTOCOL2(Xor, ^)
444-
NUMPROTOCOL2(Or, |)
445-
NUMPROTOCOL2(And, &)
446-
NUMPROTOCOL1(Invert, ~)
447-
448-
/** alsaseq.Constant number protocol methods */
449-
static PyNumberMethods Constant_as_number = {
450-
nb_add: (binaryfunc)Constant_Add,
451-
nb_subtract: (binaryfunc)Constant_Subtract,
452-
nb_xor: (binaryfunc)Constant_Xor,
453-
nb_or: (binaryfunc)Constant_Or,
454-
nb_and: (binaryfunc)Constant_And,
455-
nb_invert: (unaryfunc)Constant_Invert
456-
};
411+
CONST_EXTRA(self)->name);
412+
}
457413

458414
/** alsaseq.Constant type */
459415
static PyTypeObject ConstantType = {
@@ -464,7 +420,7 @@ static PyTypeObject ConstantType = {
464420
#else
465421
tp_base: &PyLong_Type,
466422
#endif
467-
tp_basicsize: sizeof(ConstantObject),
423+
tp_basicsize: sizeof(ConstantObject) + sizeof(ConstantExtraFields),
468424
tp_flags:
469425
#if PY_MAJOR_VERSION < 3
470426
Py_TPFLAGS_HAVE_GETCHARBUFFER
@@ -474,7 +430,6 @@ static PyTypeObject ConstantType = {
474430
0,
475431
#endif
476432
tp_doc: Constant__doc__,
477-
tp_as_number: &Constant_as_number,
478433
tp_free: PyObject_Del,
479434
tp_str: (reprfunc)Constant_str,
480435
tp_repr: (reprfunc)Constant_repr
@@ -1730,7 +1685,7 @@ SeqEvent_repr(SeqEventObject *self) {
17301685
unsigned int ntime = 0;
17311686
Py_DECREF(key);
17321687
if (constObject != NULL) {
1733-
typestr = constObject->name;
1688+
typestr = constObject->extra.name;
17341689
}
17351690

17361691
if (snd_seq_ev_is_real(self->event)) {

0 commit comments

Comments
 (0)